diff options
Diffstat (limited to 'apt-pkg/deb/dpkgpm.cc')
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 706abcb92..ce4d4b44b 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -357,7 +357,15 @@ void pkgDPkgPM::DoTerminalPty(int master) char term_buf[1024] = {0,}; int len=read(master, term_buf, sizeof(term_buf)); - if(len <= 0) + if(len == -1 && errno == EIO) + { + // this happens when the child is about to exit, we + // give it time to actually exit, otherwise we run + // into a race + usleep(500000); + return; + } + if(len <= 0) return; write(1, term_buf, len); if(term_out) @@ -816,7 +824,12 @@ bool pkgDPkgPM::Go(int OutStatusFd) // setups fds fd_set rfds; - struct timeval tv; + struct timespec tv; + sigset_t sigmask; + sigset_t original_sigmask; + sigemptyset(&sigmask); + sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask); + int select_ret; while ((res=waitpid(Child,&Status, WNOHANG)) != Child) { if(res < 0) { @@ -839,18 +852,19 @@ bool pkgDPkgPM::Go(int OutStatusFd) if(master >= 0) FD_SET(master, &rfds); tv.tv_sec = 1; - tv.tv_usec = 0; - select_ret = select(max(master, _dpkgin)+1, &rfds, NULL, NULL, &tv); - if (select_ret == 0) - continue; - else if (select_ret < 0 && errno == EINTR) - continue; - else if (select_ret < 0) - { - perror("select() returned error"); - continue; - } - + tv.tv_nsec = 0; + select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, + &tv, &original_sigmask); + if (select_ret == 0) + continue; + else if (select_ret < 0 && errno == EINTR) + continue; + else if (select_ret < 0) + { + perror("select() returned error"); + continue; + } + if(master >= 0 && FD_ISSET(master, &rfds)) DoTerminalPty(master); if(master >= 0 && FD_ISSET(0, &rfds)) |