From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 983F220087 for ; Mon, 1 Feb 2021 08:28:35 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 20/21] lei: avoid ETOOMANYREFS, cleanup imports Date: Sun, 31 Jan 2021 22:28:32 -1000 Message-Id: <20210201082833.3293-21-e@80x24.org> In-Reply-To: <20210201082833.3293-1-e@80x24.org> References: <20210201082833.3293-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: As with PublicInbox::IPC, we'll attempt to bump RLIMIT_NOFILE and transparently workaround ETOOMANYREFS. If that fails, we'll give the user a hint to bump RLIMIT_NOFILE since ETOOMANYREFS is an uncommon error which users may be unfamiliar with. Found while stress testing for segfaults. --- script/lei | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/script/lei b/script/lei index f92dd302..58f0dbe9 100755 --- a/script/lei +++ b/script/lei @@ -4,10 +4,9 @@ use strict; use v5.10.1; use Socket qw(AF_UNIX SOCK_SEQPACKET MSG_EOR pack_sockaddr_un); -use Errno qw(EINTR ECONNRESET); use PublicInbox::CmdIPC4; my $narg = 5; -my ($sock, $pwd); +my $sock; my $recv_cmd = PublicInbox::CmdIPC4->can('recv_cmd4'); my $send_cmd = PublicInbox::CmdIPC4->can('send_cmd4') // do { require PublicInbox::Spawn; # takes ~50ms even if built *sigh* @@ -73,20 +72,32 @@ connect($path): $! (after attempted daemon start) Falling back to (slow) one-shot mode } - 1; -}) { # (Socket::MsgHdr|Inline::C), $sock, $pwd are all available: + # (Socket::MsgHdr|Inline::C), $sock are all available: open my $dh, '<', '.' or die "open(.) $!"; my $buf = join("\0", scalar(@ARGV), @ARGV); while (my ($k, $v) = each %ENV) { $buf .= "\0$k=$v" } $buf .= "\0\0"; - $send_cmd->($sock, [ 0, 1, 2, fileno($dh) ], $buf, MSG_EOR) or - die "sendmsg: $!"; + my $n = $send_cmd->($sock, [0, 1, 2, fileno($dh)], $buf, MSG_EOR); + if (!$n && $!{ETOOMANYREFS} && eval { require BSD::Resource }) { + my $NOFILE = BSD::Resource::RLIMIT_NOFILE(); + my ($s, $h) = BSD::Resource::getrlimit($NOFILE); + if ($s < $h && BSD::Resource::setrlimit($NOFILE, $h, $h)) { + $n = $send_cmd->($sock, [0, 1, 2, fileno($dh)], + $buf, MSG_EOR); + } + } + if (!$n) { + die "sendmsg: $! (check RLIMIT_NOFILE)\n" if $!{ETOOMANYREFS}; + die "sendmsg: $!\n"; + } + 1; +}) { # connected and request sent to lei-daemon, wait for responses or EOF my $x_it_code = 0; while (1) { - my (@fds) = $recv_cmd->($sock, $buf, 4096 * 33); + my (@fds) = $recv_cmd->($sock, my $buf, 4096 * 33); if (scalar(@fds) == 1 && !defined($fds[0])) { - last if $! == ECONNRESET; - next if $! == EINTR; + next if $!{EINTR}; + last if $!{ECONNRESET}; die "recvmsg: $!"; } last if $buf eq '';