From e3944dfcfb3c0d8964d7cd458a9f14bbf503d00f Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 10 Aug 2020 02:11:56 +0000 Subject: [PATCH] index+xcpdb: improve SIG{INT,TERM,HUP,PIPE} behavior -index now invokes ->DESTROY like xcpdb does, which is necessary to cleanup $INBOX_DIR/msgmap-XXXXXXX files. We'll also exit with the expected values for various signals by adding 128 as described in -xcpdb now terminates worker processes and xapian-compact(1) invocations when prematurely killed, too. --- lib/PublicInbox/Admin.pm | 29 +++++++++++++++++++++++++---- lib/PublicInbox/Xapcmd.pm | 28 +++++++++++++++++++--------- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/lib/PublicInbox/Admin.pm b/lib/PublicInbox/Admin.pm index e42b01e0..af2b3da9 100644 --- a/lib/PublicInbox/Admin.pm +++ b/lib/PublicInbox/Admin.pm @@ -5,14 +5,28 @@ # Unstable internal API package PublicInbox::Admin; use strict; -use warnings; -use Cwd 'abs_path'; -use base qw(Exporter); -our @EXPORT_OK = qw(resolve_repo_dir); +use parent qw(Exporter); +use Cwd qw(abs_path); +use POSIX (); +our @EXPORT_OK = qw(resolve_repo_dir setup_signals); use PublicInbox::Config; use PublicInbox::Inbox; use PublicInbox::Spawn qw(popen_rd); +sub setup_signals { + my ($cb, $arg) = @_; # optional + + # we call exit() here instead of _exit() so DESTROY methods + # get called (e.g. File::Temp::Dir and PublicInbox::Msgmap) + $SIG{INT} = $SIG{HUP} = $SIG{PIPE} = $SIG{TERM} = sub { + my ($sig) = @_; + # https://www.tldp.org/LDP/abs/html/exitcodes.html + eval { $cb->($sig, $arg) } if $cb; + $sig = 'SIG'.$sig; + exit(128 + POSIX->$sig); + }; +} + sub resolve_repo_dir { my ($cd, $ver) = @_; my $prefix = defined $cd ? $cd : './'; @@ -185,9 +199,16 @@ invalid indexlevel=$indexlevel (must be `basic', `medium', or `full') die missing_mod_msg($err) ." required for indexlevel=$indexlevel\n"; } +sub index_terminate { + my (undef, $ibx) = @_; # $_[0] = signal name + $ibx->git->cleanup; +} + sub index_inbox { my ($ibx, $im, $opt) = @_; my $jobs = delete $opt->{jobs} if $opt; + local %SIG = %SIG; + setup_signals(\&index_terminate, $ibx); if (ref($ibx) && $ibx->version == 2) { eval { require PublicInbox::V2Writable }; die "v2 requirements not met: $@\n" if $@; diff --git a/lib/PublicInbox/Xapcmd.pm b/lib/PublicInbox/Xapcmd.pm index 714f6859..348621ce 100644 --- a/lib/PublicInbox/Xapcmd.pm +++ b/lib/PublicInbox/Xapcmd.pm @@ -2,8 +2,8 @@ # License: AGPL-3.0+ package PublicInbox::Xapcmd; use strict; -use warnings; use PublicInbox::Spawn qw(which popen_rd nodatacow_dir); +use PublicInbox::Admin qw(setup_signals); use PublicInbox::Over; use PublicInbox::SearchIdx; use File::Temp 0.19 (); # ->newdir @@ -126,6 +126,11 @@ sub same_fs_or_die ($$) { die "$x and $y reside on different filesystems\n"; } +sub kill_pids { + my ($sig, $pids) = @_; + kill($sig, keys %$pids); # pids may be empty +} + sub process_queue { my ($queue, $cb, $opt) = @_; my $max = $opt->{jobs} // scalar(@$queue); @@ -138,6 +143,8 @@ sub process_queue { # run in parallel: my %pids; + local %SIG = %SIG; + setup_signals(\&kill_pids, \%pids); while (@$queue) { while (scalar(keys(%pids)) < $max && scalar(@$queue)) { my $args = shift @$queue; @@ -156,12 +163,6 @@ sub process_queue { } } -sub setup_signals () { - # http://www.tldp.org/LDP/abs/html/exitcodes.html - $SIG{INT} = sub { exit(130) }; - $SIG{HUP} = $SIG{PIPE} = $SIG{TERM} = sub { exit(1) }; -} - sub prepare_run { my ($ibx, $opt) = @_; my $tmp = {}; # old shard dir => File::Temp->newdir object or undef @@ -294,6 +295,11 @@ sub progress_pfx ($) { ($p[-1] =~ /\A([0-9]+)/) ? "$p[-2]/$1" : $p[-1]; } +sub kill_compact { # setup_signals callback + my ($sig, $pidref) = @_; + kill($sig, $$pidref) if defined($$pidref); +} + # xapian-compact wrapper sub compact ($$) { my ($args, $opt) = @_; @@ -319,14 +325,18 @@ sub compact ($$) { } $pr->("$pfx `".join(' ', @$cmd)."'\n") if $pr; push @$cmd, $src, $dst; - my $rd = popen_rd($cmd, undef, $rdr); + my ($rd, $pid); + local %SIG = %SIG; + setup_signals(\&kill_compact, \$pid); + ($rd, $pid) = popen_rd($cmd, undef, $rdr); while (<$rd>) { if ($pr) { s/\r/\r$pfx /g; $pr->("$pfx $_"); } } - close $rd or die join(' ', @$cmd)." failed: $?n"; + waitpid($pid, 0); + die "@$cmd failed: \$?=$?\n" if $?; } sub cpdb_loop ($$$;$$) { -- 2.44.0