我正在尝试将对spawnp的调用转换为fork-exec。 但是在我正在处理的代码中,他们正在使用继承数据结构将一些信号设置传递给子代。具体如下:
memset(&inheritance, 0, sizeof(inheritance));
inheritance.flags = SPAWN_SETSIGDEF;
sigfillset(&inheritance.sigdefault);
inheritance.sigmask = some_default_sig_mask;
spawnp(.......);
如何在不使用spawnp的情况下传递信号设置?我是否使用sigfillset和pthread_procmask函数?如果是这样,这种语法是否正确?如果我只是在sigfillset()中设置sigset变量,那么设置将如何传递给相关进程?
fork();
if (child process)
sigemptyset(sigset)
sigfillset(sigset)
pthread_procmask(SIG_SETMASK, some_default_sig_mask, NULL);
感谢您的帮助!
答案 0 :(得分:1)
您需要实现两件事:重置某些信号的信号处理(SPAWN_SETSIGDEF行为),以及设置新进程的掩码(SPAWN_SETSIGMASK行为)。
(请注意,在发布的示例中,您实际上并没有执行后者,但您打算这样做是合理的。)
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只是设置新进程的信号掩码,您可以通过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);