From e748f75979046724ead380bd00eadc677bdc07e9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 18 Jun 2016 10:53:32 +0000 Subject: spawn: try to keep signals blocked in spawned child While we only want to stop our daemons and gracefully destroy subprocesses, it is common for 'Ctrl-C' from a terminal to kill the entire pgroup. Killing an entire pgroup nukes subprocesses like git-upload-pack breaks graceful shutdown on long clones. Make a best effort to ensure git-upload-pack processes are not broken when somebody signals an entire process group. Followup-to: commit 37bf2db81bbbe114d7fc5a00e30d3d5a6fa74de5 ("doc: systemd examples should only kill one process") --- lib/PublicInbox/Spawn.pm | 8 +++++--- lib/PublicInbox/SpawnPP.pm | 7 ++++++- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'lib/PublicInbox') diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm index 66dce335..83730302 100644 --- a/lib/PublicInbox/Spawn.pm +++ b/lib/PublicInbox/Spawn.pm @@ -104,9 +104,11 @@ int public_inbox_fork_exec(int in, int out, int err, REDIR(out, 1); REDIR(err, 2); for (sig = 1; sig < NSIG; sig++) - signal(sig, SIG_DFL); /* ignore errorrs on signals */ - ret = sigprocmask(SIG_SETMASK, &old, NULL); - if (ret != 0) xerr("sigprocmask failed in vfork child"); + signal(sig, SIG_DFL); /* ignore errors on signals */ + /* + * don't bother unblocking, we don't want signals + * to the group taking out a subprocess + */ execve(filename, argv, envp); xerr("execve failed"); } diff --git a/lib/PublicInbox/SpawnPP.pm b/lib/PublicInbox/SpawnPP.pm index fe95d126..36223e81 100644 --- a/lib/PublicInbox/SpawnPP.pm +++ b/lib/PublicInbox/SpawnPP.pm @@ -3,11 +3,15 @@ package PublicInbox::SpawnPP; use strict; use warnings; -use POSIX qw(dup2); +use POSIX qw(dup2 :signal_h); # Pure Perl implementation for folks that do not use Inline::C sub public_inbox_fork_exec ($$$$$$) { my ($in, $out, $err, $f, $cmd, $env) = @_; + my $old = POSIX::SigSet->new(); + my $set = POSIX::SigSet->new(); + $set->fillset or die "fillset failed: $!"; + sigprocmask(SIG_SETMASK, $set, $old) or die "can't block signals: $!"; my $pid = fork; if ($pid == 0) { if ($in != 0) { @@ -29,6 +33,7 @@ sub public_inbox_fork_exec ($$$$$$) { die "exec $cmd->[0] failed: $!\n"; } } + sigprocmask(SIG_SETMASK, $old) or die "can't unblock signals: $!"; $pid; } -- cgit v1.2.3-24-ge0c7