Craig Sanders <c...@taz.net.au> writes: > On Wed, Jan 12, 2022 at 06:06:45PM -0500, Aaron M. Ucko wrote: >> Long story short, update-dpkg-list's batched bidirectional pipe usage wound >> up deadlocking on a system with 20,000+ provided virtual packages, mostly >> from installed librust-*-dev packages. > > what do you mean by "deadlocking"? some kind of lockup, i presume. what > exactly happens? roughly how long is the script running before it happens?
As confirmed by strace, each side of the pipe is blocking on a write call that won't complete until the other side issues a read, because the kernel's buffer for the pipe has filled up. I am comfortable with Perl, and having taken another look at the code, was able to resolve the deadlock by arranging to feed xargs from a dedicated subprocess, per the attached patch. Could you please consider applying it? Thanks! -- Aaron M. Ucko, KB1CJC (amu at alum.mit.edu, ucko at debian.org) http://www.mit.edu/~amu/ | http://stuff.mit.edu/cgi/finger/?a...@monk.mit.edu
diff -u update-dpkg-list~ update-dpkg-list --- update-dpkg-list~ 2022-01-13 20:52:49.875888185 -0500 +++ update-dpkg-list 2022-01-13 21:41:42.053617442 -0500 @@ -4,6 +4,7 @@ use warnings; use IPC::Open2; use File::Basename; +use POSIX qw(:sys_wait_h); my $program = basename($0); @@ -59,14 +60,20 @@ # apt-cache doesn't read stdin, so we have to use xargs to make sure we # never exceed the bash command line limit. my $pid = open2(\*ACS, \*XARGS, 'xargs -0r apt-cache show'); + my $pid2 = fork(); - print XARGS join("\0",@unknown); - close(XARGS); + if ($pid2 == 0) { + print XARGS join("\0",@unknown); + exit(0); + } else { + close(XARGS); + } while (<ACS>) { parse_pkg('ACS',$_); }; close(ACS); + waitpid($pid2, WNOHANG); }; my $dlist = '/var/lib/dlocate/dpkg-list';