您需要影响两件事:重置某些信号的信号配置(SPAWN_SETSIGDEF 行为),以及设置新进程的掩码(SPAWN_SETSIGMASK 行为)。
(请注意,在您发布的示例中,您实际上并没有做后者,但您打算这样做是合理的。)
SPAWN_SETSIGDEF
SPAWN_SETSIGDEF 重置sigdefault
集合中所有信号的配置。您可以通过在您希望设置为默认处置的每个单独信号上调用sigaction()来实现这一点:
int spawnlike_setsigdef(const sigset_t *s) { /* FIXME: assert(s != NULL) */
int signum;
struct sigaction sa = { 0 };
sa.sa_handler = SIG_DFL;
for (signum = 1; signum < NSIG; signum++) { /* You might have to use _NSIG or */
if (! sigismember(s, signum)) continue; /* SIGRTMAX or similar. */
switch (signum) {
case SIGKILL:
case SIGSTOP: /* Can't modify disposition of these */
break;
default:
if (sigaction(signum, &sa, NULL) == -1)
return -1; /* Yikes! What happened? */
}
}
return 0;
}
SPAWN_SETSIGMASK
SPAWN_SETSIGMASK 只是设置新进程的信号掩码,您可以通过pthread_sigmask()或sigprocmask()来完成:
顺便说一句,您没有在 spawnp() 片段中指定 SPAWN_SETSIGMASK,因此您实际上并没有明确设置新进程的掩码。(它会像往常一样继承掩码。)
把它放在一起
你会想要这样的东西:
sigset_t all_signals;
sigset_t saved_mask;
sigfillset(&all_signals);
/* Now protect our child as best we can between resetting dispo to SIG_DFL
* and setting default sig mask. We'll also reuse 'all_signals' later in
* the newly fork()d child.
*/
pthread_sigmask(SIG_SETMASK, &all_signals, &saved_mask);
if (fork() == 0) {
/* am child */
spawnlike_setsigdef(all_signals);
sigprocmask(SIG_SETMASK, &some_default_sig_mask, NULL);
execv(...);
fatal_error("execv didn't work :(\n");
}
/* else I am parent, restore my original mask */
pthread_sigmask(SIG_SETMASK, &all_signals, &saved_mask);