From: Eric Wong Date: Thu, 9 Nov 2023 10:09:42 +0000 (+0000) Subject: ipc: simplify partial sendmsg fallback X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b35530ccb929a693c4c78b02187a564a7ab5e903;p=thirdparty%2Fpublic-inbox.git ipc: simplify partial sendmsg fallback In the rare case sendmsg(2) isn't able to send the full amount (due to buffers >=2GB on Linux), use print + (autodie)close to send the remainder and retry on EINTR. `substr' should be able to avoid a large malloc via offsets and CoW on modern Perl. --- diff --git a/lib/PublicInbox/IPC.pm b/lib/PublicInbox/IPC.pm index 3292d9604..a5cae6f2e 100644 --- a/lib/PublicInbox/IPC.pm +++ b/lib/PublicInbox/IPC.pm @@ -10,7 +10,7 @@ package PublicInbox::IPC; use v5.12; use parent qw(Exporter); -use autodie qw(fork pipe read socketpair sysread); +use autodie qw(close fork pipe read socketpair sysread); use Carp qw(croak); use PublicInbox::DS qw(awaitpid); use PublicInbox::Spawn; @@ -266,15 +266,8 @@ sub stream_in_full ($$$) { 0) // croak "sendmsg: $!"; undef $r; $n = $send_cmd->($w, $fds, $buf, 0) // croak "sendmsg: $!"; - while ($n < length($buf)) { - my $x = syswrite($w, $buf, length($buf) - $n, $n); - if (!defined($n)) { - next if $!{EINTR}; - croak "syswrite: $!"; - } - $x or croak "syswrite wrote 0 bytes"; - $n += $x; - } + print $w substr($buf, $n) if $n < length($buf); # need > 2G on Linux + close $w; # autodies } sub wq_io_do { # always async diff --git a/t/ipc.t b/t/ipc.t index 519ef089b..23ae2e7b2 100644 --- a/t/ipc.t +++ b/t/ipc.t @@ -132,6 +132,13 @@ for my $t ('worker', 'worker again') { $exp = sha1_hex($bigger)."\n"; is(readline($rb), $exp, "SHA WQWorker limit ($t)"); } + SKIP: { + $ENV{TEST_EXPENSIVE} or skip 'TEST_EXPENSIVE not set', 1; + my $bigger = $big x 75000; # over 2G to trigger partial sendmsg + $ipc->wq_io_do('test_sha', [ $wa, $wb ], $bigger); + my $exp = sha1_hex($bigger)."\n"; + is(readline($rb), $exp, "SHA WQWorker sendmsg limit ($t)"); + } } # wq_io_do works across fork (siblings can feed)