From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, T_SCC_BODY_TEXT_LINE shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 3B7921F51A for ; Tue, 20 Aug 2024 10:35:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1724150123; bh=99iZkjMwC20rvQCJCcmLPto3tqzEAtZoPVq4hTj6PP0=; h=From:To:Subject:Date:In-Reply-To:References:From; b=V9z6CNzWwhLINnvJumfNoAB3Tn0ST7rYNXp1GVgUnJhCpgaFkM1m7c073Kx6IbYag nG+AAc8QttLt6t/upEKF1fefviJ5QmqygihDHj8a5+iA/0bCyRuPiWSS8UwZ2Wd8SN nvoGEX59ezhapammc9ubgegC6aGvSzTCMC8T4W4Q= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 4/5] lei: allow Ctrl-C to interrupt IMAP+NNTP reads Date: Tue, 20 Aug 2024 10:35:20 +0000 Message-ID: <20240820103522.3548609-5-e@80x24.org> In-Reply-To: <20240820103522.3548609-1-e@80x24.org> References: <20240820103522.3548609-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Mail::IMAPClient and Net::NNTP remain synchronous APIs with indefinite wait times on slow/unreliable connections or servers. Since these APIs don't play nicely with signalfd or EVFILT_SIGNAL, we will temporarily drop the reliable (but sometimes delayed) signal handling mechanisms in favor of the less reliable built-in signal handling of Perl to provide a best-effort attempt to handle signals during slow operations. --- lib/PublicInbox/NetReader.pm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/PublicInbox/NetReader.pm b/lib/PublicInbox/NetReader.pm index 7e861f5f..b95022b3 100644 --- a/lib/PublicInbox/NetReader.pm +++ b/lib/PublicInbox/NetReader.pm @@ -7,6 +7,7 @@ use v5.12; use parent qw(Exporter PublicInbox::IPC); use PublicInbox::Eml; use PublicInbox::Config; +use PublicInbox::DS; our %IMAPflags2kw = map {; "\\\u$_" => $_ } qw(seen answered flagged draft); $IMAPflags2kw{'$Forwarded'} = 'forwarded'; # RFC 5550 @@ -61,6 +62,7 @@ sub mic_new ($$$$) { my %mic_arg = (%$mic_arg, Keepalive => 1); my $sa = $self->{cfg_opt}->{$sec}->{-proxy_cfg} || $self->{-proxy_cli}; my ($mic, $s, $t); + my $restore = PublicInbox::DS::allow_sigs qw(INT QUIT TERM); if ($sa) { # this `require' needed for worker[1..Inf], since socks_args # only got called in worker[0] @@ -226,6 +228,7 @@ sub nn_new ($$$$) { ($Net_NNTP, $new) = qw(PublicInbox::NetNNTPSocks new_socks); $nn_arg->{SocksDebug} = 1 if $nn_arg->{Debug}; } + my $restore = PublicInbox::DS::allow_sigs qw(INT QUIT TERM); do { $! = 0; $nn = $Net_NNTP->$new(%$nn_arg); @@ -567,12 +570,14 @@ sub each_old_flags ($$$$) { for (my $n = 1; $n <= $l_uid; $n += $bs) { my $end = $n + $bs; $end = $l_uid if $end > $l_uid; + my $restore = PublicInbox::DS::allow_sigs qw(INT QUIT TERM); my $r = $mic->fetch_hash("$n:$end", 'FLAGS'); if (!$r) { return if $!{EINTR} && $self->{quit}; return "E: $uri UID FETCH $n:$end error: " . $mic->LastError." \$!=$!" } + undef $restore; while (my ($uid, $per_uid) = each %$r) { my $kw = flags2kw($self, $uri, $uid, $per_uid->{FLAGS}) // next; @@ -611,12 +616,14 @@ sub _imap_fetch_bodies ($$$$) { my @batch = splice(@$uids, 0, $bs); my $batch = join(',', @batch); local $0 = "UID:$batch $mbx $sec"; + my $restore = PublicInbox::DS::allow_sigs qw(INT QUIT TERM); my $r = $mic->fetch_hash($batch, $req, 'FLAGS'); unless ($r) { # network error? last if $!{EINTR} && $self->{quit}; $err = "E: $uri UID FETCH $batch error: $!"; last; } + undef $restore; for my $uid (@batch) { # messages get deleted, so holes appear my $per_uid = delete $r->{$uid} // next; @@ -640,6 +647,7 @@ sub _imap_fetch_all ($$$) { # we need to check for mailbox writability to see if we care about # FLAGS from already-imported messages. my $cmd = $self->folder_select; + my $restore = PublicInbox::DS::allow_sigs qw(INT QUIT TERM); $mic->$cmd($mbx) or return "E: \U$cmd\E $mbx ($sec) failed: $!"; my ($r_uidval, $r_uidnext, $perm_fl); @@ -657,6 +665,7 @@ sub _imap_fetch_all ($$$) { E: $orig_uri UIDVALIDITY mismatch (got $r_uidval) EOF + undef $restore; my $uri = $orig_uri->clone; my $single_uid = $uri->uid; my ($itrk, $l_uid, $l_uidval) = itrk_last($self, $uri, $r_uidval, $mic); @@ -782,6 +791,7 @@ sub nn_get { my $nntp_cfg = $self->{cfg_opt}->{$sec}; $nn = nn_new($self, $nn_arg, $nntp_cfg, $uri) or return; if (my $postconn = $nntp_cfg->{-postconn}) { + my $restore = PublicInbox::DS::allow_sigs qw(INT QUIT TERM); for my $m_arg (@$postconn) { my ($method, @args) = @$m_arg; $nn->$method(@args) and next; @@ -796,11 +806,13 @@ sub _nntp_fetch_all ($$$) { my ($self, $nn, $uri) = @_; my ($group, $num_a, $num_b) = $uri->group; my $sec = uri_section($uri); + my $restore = PublicInbox::DS::allow_sigs qw(INT QUIT TERM); my ($nr, $beg, $end) = $nn->group($group); unless (defined($nr)) { my $msg = ndump($nn->message); return "E: GROUP $group <$sec> $msg"; } + undef $restore; (defined($num_a) && defined($num_b) && $num_a > $num_b) and return "E: $uri: backwards range: $num_a > $num_b"; if (defined($num_a)) { # no article numbers in mail_sync.sqlite3 @@ -833,6 +845,7 @@ sub _nntp_fetch_all ($$$) { $itrk->update_last(0, $last_art) if $itrk; $n = $self->{max_batch}; } + $restore = PublicInbox::DS::allow_sigs qw(INT QUIT TERM); my $raw = $nn->article($art); unless (defined($raw)) { my $msg = ndump($nn->message); @@ -844,6 +857,7 @@ sub _nntp_fetch_all ($$$) { next; } } + undef $restore; $raw = join('', @$raw); $raw =~ s/\r\n/\n/sg; my ($eml_cb, @args) = @{$self->{eml_each}};