Необходимо выполнить две вещи: сброс расположения сигналов для некоторых сигналов (поведение 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 () :
Кстати, , вы не указываете SPAWN_SETSIGMASK в своем фрагменте spawnp (), так что вы фактически не устанавливаете маску нового процесса в явном виде. (Вместо этого она наследует маску как обычно.)
Собираем все вместе
Вы захотите что-то вроде этого:
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);