Package: apt Version: 0.7.20.2+lenny2 Severity: normal Tags: patch
#apt-get -s dist-upgrade Reading package lists... Done Building dependency tree Reading state information... Done Calculating upgrade... Done The following packages have been kept back: acroread-debian-files fvwm gdk-imlib11 gtk-engines-lighthouseblue libgtk1.2 lvm2 The following packages will be upgraded: gzip 1 upgraded, 0 newly installed, 0 to remove and 6 not upgraded. Inst gzip [1.3.12-6+lenny] (1.3.12-6+lenny1 Debian:5.0.5/stable, Debian-Security:5.0/stable) Conf gzip (1.3.12-6+lenny1 Debian:5.0.5/stable, Debian-Security:5.0/stable) `yes '' | apt-get dist-upgrade' causes apt-get to block in write(2) because nobody reads (or even has open) the pseudoterminal it writes to (since its child, dpkg, is a zombie already). Please see the patch for details. Thanks. -- Package-specific info: -- apt-config dump -- APT ""; APT::Architecture "i386"; APT::Build-Essential ""; APT::Build-Essential:: "build-essential"; APT::Install-Recommends "1"; APT::Install-Suggests "0"; APT::Acquire ""; APT::Acquire::Translation "environment"; APT::NeverAutoRemove ""; APT::NeverAutoRemove:: "^linux-image.*"; APT::NeverAutoRemove:: "^linux-restricted-modules.*"; APT::Cache-Limit "16777216"; Dir "/"; Dir::State "var/lib/apt/"; Dir::State::lists "lists/"; Dir::State::cdroms "cdroms.list"; Dir::State::userstatus "status.user"; Dir::State::status "/var/lib/dpkg/status"; Dir::Cache "var/cache/apt/"; Dir::Cache::archives "archives/"; Dir::Cache::srcpkgcache "srcpkgcache.bin"; Dir::Cache::pkgcache "pkgcache.bin"; Dir::Etc "etc/apt/"; Dir::Etc::sourcelist "sources.list"; Dir::Etc::sourceparts "sources.list.d"; Dir::Etc::vendorlist "vendors.list"; Dir::Etc::vendorparts "vendors.list.d"; Dir::Etc::main "apt.conf"; Dir::Etc::parts "apt.conf.d"; Dir::Etc::preferences "preferences"; Dir::Bin ""; Dir::Bin::methods "/usr/lib/apt/methods"; Dir::Bin::dpkg "/usr/bin/dpkg"; Dir::Log "var/log/apt"; Dir::Log::Terminal "term.log"; DPkg ""; DPkg::Pre-Install-Pkgs ""; DPkg::Pre-Install-Pkgs:: "/usr/sbin/dpkg-preconfigure --apt || true"; DPkg::Post-Invoke ""; DPkg::Post-Invoke:: "if [ -x /usr/bin/debsums ]; then /usr/bin/debsums --generate=nocheck -sp /var/cache/apt/archives; fi"; DPkg::Post-Invoke:: "test -f /var/run/junior-config.usermenu && if [ -x /usr/sbin/cdd-update-usermenus ] ; then /usr/sbin/cdd-update-usermenus junior ; fi ; rm -f /var/run/junior-config.usermenu"; -- /etc/apt/preferences -- Package: * Pin: release a=stable Pin-Priority: 600 Package: * Pin: release a=oldstable Pin-Priority: 50 -- (/etc/apt/sources.list present, but not submitted) -- -- System Information: Debian Release: 5.0.5 APT prefers stable APT policy: (600, 'stable') Architecture: i386 (i686) Kernel: Linux 2.6.26-1-686 (SMP w/1 CPU core) Locale: LANG=ru_RU.UTF-8, LC_CTYPE=ru_RU.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages apt depends on: ii debian-archive-keyring 2009.01.31 GnuPG archive keys of the Debian a ii libc6 2.7-18lenny4 GNU C Library: Shared libraries ii libgcc1 1:4.3.2-1.1 GCC support library ii libstdc++6 4.3.2-1.1 The GNU Standard C++ Library v3 apt recommends no packages. Versions of packages apt suggests: pn apt-doc <none> (no description available) ii aptitude 0.4.11.11-1~lenny1 terminal-based package manager ii bzip2 1.0.5-1 high-quality block-sorting file co ii dpkg-dev 1.14.29 Debian package development tools ii lzma 4.43-14 Compression method of 7z format in ii python-apt 0.7.7.1+nmu1 Python interface to libapt-pkg -- no debconf information
`yes '' | apt-get dist-upgrade' causes apt-get to block in write because nobody reads (or even has open) the pseudoterminal it writes to (since its child, dpkg, is a zombie already). Also, this patch fixes the follwing problems: * If write(2) in DoStdin writes not the whole input_buf (or interrupted), the rest of input_buf would be lost. * If read(2) in DoStdin fails, write(2) would be called with a negative `count' argument. -- /Dmitry Maksyoma <dmaks...@allot.com> diff -ru apt-0.7.20.2+lenny2/apt-pkg/deb/dpkgpm.cc /home/dmaks/devel/6.0/apt/apt-0.7.20.2+lenny2/apt-pkg/deb/dpkgpm.cc --- apt-0.7.20.2+lenny2/apt-pkg/deb/dpkgpm.cc 2009-02-08 04:09:35.000000000 +1300 +++ /home/dmaks/devel/6.0/apt/apt-0.7.20.2+lenny2/apt-pkg/deb/dpkgpm.cc 2010-08-11 16:56:03.000000000 +1200 @@ -81,6 +81,7 @@ : pkgPackageManager(Cache), dpkgbuf_pos(0), term_out(NULL), PackagesDone(0), PackagesTotal(0) { + stdin_buf_start = stdin_buf_end = 0; } /*}}}*/ // DPkgPM::pkgDPkgPM - Destructor /*{{{*/ @@ -314,12 +315,39 @@ */ void pkgDPkgPM::DoStdin(int master) { - unsigned char input_buf[256] = {0,}; - ssize_t len = read(0, input_buf, sizeof(input_buf)); - if (len) - write(master, input_buf, len); - else - stdin_is_dev_null = true; + ssize_t to_write_len = stdin_buf_end - stdin_buf_start; + + // Read from stdin only if there's nothing in the stdin_buf. + if (to_write_len == 0) { + ssize_t len; + while ((len = read(0, stdin_buf, sizeof(stdin_buf))) == EINTR); + if (len <= 0) { + // Stop reading from stdin when end of file was reached or there are + // problems with rd. + stdin_is_dev_null = true; + return; + } + + to_write_len = len; + stdin_buf_start = 0; + stdin_buf_end = len; + } + + if (master != -1 && to_write_len) { + ssize_t wrote_len; + while ((wrote_len = + write(master, &stdin_buf[stdin_buf_start], to_write_len)) == EINTR); + + if (wrote_len < 0) { + perror("write"); + return; + } + + if (wrote_len == to_write_len) + stdin_buf_start = stdin_buf_end = 0; + else + stdin_buf_start += wrote_len; + } } /*}}}*/ // DPkgPM::DoTerminalPty - Read the terminal pty and write log /*{{{*/ @@ -866,6 +894,7 @@ // setups fds fd_set rfds; + fd_set wfds; struct timespec tv; sigset_t sigmask; sigset_t original_sigmask; @@ -890,17 +919,20 @@ // wait for input or output here FD_ZERO(&rfds); - if (!stdin_is_dev_null) + if (!stdin_is_dev_null && stdin_buf_end == 0) FD_SET(0, &rfds); FD_SET(_dpkgin, &rfds); if(master >= 0) FD_SET(master, &rfds); + FD_ZERO(&wfds); + if(master >= 0) + FD_SET(master, &wfds); tv.tv_sec = 1; tv.tv_nsec = 0; - select_ret = pselect(max(master, _dpkgin)+1, &rfds, NULL, NULL, + select_ret = pselect(max(master, _dpkgin)+1, &rfds, &wfds, NULL, &tv, &original_sigmask); if (select_ret < 0 && (errno == EINVAL || errno == ENOSYS)) - select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, NULL, + select_ret = racy_pselect(max(master, _dpkgin)+1, &rfds, &wfds, NULL, &tv, &original_sigmask); if (select_ret == 0) continue; @@ -914,8 +946,8 @@ if(master >= 0 && FD_ISSET(master, &rfds)) DoTerminalPty(master); - if(master >= 0 && FD_ISSET(0, &rfds)) - DoStdin(master); + if(master >= 0 && (stdin_buf_end > 0 || FD_ISSET(0, &rfds))) + DoStdin(FD_ISSET(master, &wfds) ? master : -1); if(FD_ISSET(_dpkgin, &rfds)) DoDpkgStatusFd(_dpkgin, OutStatusFd); } diff -ru apt-0.7.20.2+lenny2/apt-pkg/deb/dpkgpm.h /home/dmaks/devel/6.0/apt/apt-0.7.20.2+lenny2/apt-pkg/deb/dpkgpm.h --- apt-0.7.20.2+lenny2/apt-pkg/deb/dpkgpm.h 2009-02-08 04:09:35.000000000 +1300 +++ /home/dmaks/devel/6.0/apt/apt-0.7.20.2+lenny2/apt-pkg/deb/dpkgpm.h 2010-08-11 12:53:48.000000000 +1200 @@ -29,6 +29,11 @@ char dpkgbuf[1024]; int dpkgbuf_pos; FILE *term_out; + + // the buffer for reading stdin + unsigned char stdin_buf[256]; + unsigned int stdin_buf_start; + unsigned int stdin_buf_end; protected: