-regen_fmt => "%u/?\n",
};
local $SIG{USR1} = sub { $need_checkpoint = 1 };
+ my $quit = sub { $sync->{quit} = 1; warn "gracefully quitting\n"; };
+ local $SIG{QUIT} = $quit;
+ local $SIG{INT} = $quit;
+ local $SIG{TERM} = $quit;
# don't use $_ here, it'll get clobbered by reindex_checkpoint
for my $ibx (@{$self->{ibx_list}}) {
_sync_inbox($self, $sync, $ibx);
+ last if $sync->{quit};
}
- $self->{oidx}->rethread_done($opt);
+ $self->{oidx}->rethread_done($opt) unless $sync->{quit};
PublicInbox::V2Writable::done($self);
}
# start off in write-only mode
sub new {
open(my $io, '+>', undef) or die "open: $!";
+ # latest_cmt is still useful when the newest revision is a `d'(elete),
+ # otherwise we favor $sync->{latest_cmt} for checkpoints and {quit}
bless { wr => $io, latest_cmt => $_[1] }, __PACKAGE__
}
use bytes qw(length);
use IO::Handle (); # autoflush
use PublicInbox::Eml;
+use PublicInbox::Sigfd;
sub new {
my ($class, $v2w, $shard) = @_; # v2w may be ExtSearchIdx
my ($r, $w);
pipe($r, $w) or die "pipe failed: $!\n";
$w->autoflush(1);
+ my $oldset = PublicInbox::Sigfd::block_signals();
my $pid = fork;
defined $pid or die "fork failed: $!\n";
if ($pid == 0) {
+ # these signals are localized in parent
+ $SIG{$_} = 'IGNORE' for (qw(TERM INT QUIT));
+ PublicInbox::Sigfd::sig_setmask($oldset);
my $bnote = $v2w->atfork_child;
close $w or die "failed to close: $!";
die "unexpected MM $self->{mm}" if $self->{mm};
exit;
}
+ PublicInbox::Sigfd::sig_setmask($oldset);
$self->{pid} = $pid;
$self->{w} = $w;
close $r or die "failed to close: $!";
$unit->{stack} = $stk; # may be undef
unshift @{$sync->{todo}}, $unit;
$regen_max += $nr;
+ last if $sync->{quit};
}
# XXX this should not happen unless somebody bypasses checks in
$oid = unpack('H*', $oid);
my $req = { %$sync, oid => $oid };
$self->git->cat_async($oid, $unindex_oid, $req);
+ last if $sync->{quit};
}
$self->git->cat_async_wait;
}
+ return 0 if $sync->{quit};
if (!$regen_max) {
$sync->{-regen_fmt} = "%u/?\n";
return 0;
sub index_todo ($$$) {
my ($self, $sync, $unit) = @_;
+ return if $sync->{quit};
unindex_todo($self, $sync, $unit);
my $stk = delete($unit->{stack}) or return;
my $all = $self->git;
} elsif ($f eq 'd') {
$all->cat_async($oid, $unindex_oid, $req);
}
+ if ($sync->{quit}) {
+ warn "waiting to quit...\n";
+ $all->async_wait_all;
+ $self->update_last_commit($sync);
+ return;
+ }
if (${$sync->{need_checkpoint}}) {
reindex_checkpoint($self, $sync);
}
ibx => $self->{ibx},
epoch_max => $epoch_max,
};
+ my $quit = sub { $sync->{quit} = 1 };
+ local $SIG{QUIT} = $quit;
+ local $SIG{INT} = $quit;
+ local $SIG{TERM} = $quit;
+
if (sync_prepare($self, $sync)) {
# tmp_clone seems to fail if inside a transaction, so
# we rollback here (because we opened {mm} for reading)
}
# work forwards through history
index_todo($self, $sync, $_) for @{delete($sync->{todo}) // []};
- $self->{oidx}->rethread_done($opt);
+ $self->{oidx}->rethread_done($opt) unless $sync->{quit};
$self->done;
if (my $nr = $sync->{nr}) {