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';

Reply via email to