From 975dffc9bcb96f10bdc8a70bf6af67c2b46ab4b5 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 7 Feb 2021 08:51:43 +0000 Subject: spawn: pi_fork_exec: restore parent sigmask in child We continue to unblock SIGCHLD unconditionally, but also any signals not blocked by the parent (wq_worker). This will allow Ctrl-C (SIGINT) to stop "git clone" and allow git-clone cleanup to be performed and other long-running processes when pi_fork_exec supports setpgid(2). This won't affect existing daemons on systems with signalfd(2) or EVFILT_SIGNAL at all, since those run with signals blocked anyways. --- lib/PublicInbox/Spawn.pm | 26 ++++++++++++-------------- lib/PublicInbox/SpawnPP.pm | 6 ++---- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm index f7dcb024..bac24dd1 100644 --- a/lib/PublicInbox/Spawn.pm +++ b/lib/PublicInbox/Spawn.pm @@ -82,20 +82,20 @@ int pi_fork_exec(SV *redirref, SV *file, SV *cmdref, SV *envref, SV *rlimref, const char *filename = SvPV_nolen(file); pid_t pid; char **argv, **envp; - sigset_t set, old, cset; + sigset_t set, old; int ret, perrnum, cerrnum = 0; + int chld_is_member; AV2C_COPY(argv, cmd); AV2C_COPY(envp, env); - ret = sigfillset(&set); - assert(ret == 0 && "BUG calling sigfillset"); - ret = sigprocmask(SIG_SETMASK, &set, &old); - assert(ret == 0 && "BUG calling sigprocmask to block"); - ret = sigemptyset(&cset); - assert(ret == 0 && "BUG calling sigemptyset"); - ret = sigaddset(&cset, SIGCHLD); - assert(ret == 0 && "BUG calling sigaddset for SIGCHLD"); + if (sigfillset(&set)) return -1; + if (sigprocmask(SIG_SETMASK, &set, &old)) return -1; + chld_is_member = sigismember(&old, SIGCHLD); + if (chld_is_member < 0) return -1; + if (chld_is_member > 0) + sigdelset(&old, SIGCHLD); + pid = vfork(); if (pid == 0) { int sig; @@ -127,15 +127,13 @@ int pi_fork_exec(SV *redirref, SV *file, SV *cmdref, SV *envref, SV *rlimref, exit_err(&cerrnum); } - /* - * don't bother unblocking other signals for now, just SIGCHLD. - * we don't want signals to the group taking out a subprocess - */ - (void)sigprocmask(SIG_UNBLOCK, &cset, NULL); + (void)sigprocmask(SIG_SETMASK, &old, NULL); execve(filename, argv, envp); exit_err(&cerrnum); } perrnum = errno; + if (chld_is_member > 0) + sigaddset(&old, SIGCHLD); ret = sigprocmask(SIG_SETMASK, &old, NULL); assert(ret == 0 && "BUG calling sigprocmask to restore"); if (cerrnum) { diff --git a/lib/PublicInbox/SpawnPP.pm b/lib/PublicInbox/SpawnPP.pm index b0ad4da5..f64b95dc 100644 --- a/lib/PublicInbox/SpawnPP.pm +++ b/lib/PublicInbox/SpawnPP.pm @@ -37,10 +37,8 @@ sub pi_fork_exec ($$$$$$) { chdir $cd or die "chdir $cd: $!"; } $SIG{$_} = 'DEFAULT' for keys %SIG; - my $cset = POSIX::SigSet->new(); - $cset->addset(POSIX::SIGCHLD) or die "can't add SIGCHLD: $!"; - sigprocmask(SIG_UNBLOCK, $cset) or - die "can't unblock SIGCHLD: $!"; + $old->delset(POSIX::SIGCHLD) or die "delset SIGCHLD: $!"; + sigprocmask(SIG_SETMASK, $old) or die "SETMASK: ~SIGCHLD: $!"; if ($ENV{MOD_PERL}) { exec which('env'), '-i', @$env, @$cmd; die "exec env -i ... $cmd->[0] failed: $!\n"; -- cgit v1.2.3-24-ge0c7