如何在Linux中使用sig * set函数?

时间:2011-07-14 17:12:42

标签: linux fork signals spawn

我正在尝试将对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);

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

您需要实现两件事:重置某些信号的信号处理(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);