开发者

How to use sig*set functions in Linux?

I am trying to convert a call to spawnp to fork-exec. But in the code I am working on, they are using the inheritance data structure to pass on some signal settings to the child. These are a开发者_如何学运维s follows:

memset(&inheritance, 0, sizeof(inheritance));
inheritance.flags = SPAWN_SETSIGDEF;
sigfillset(&inheritance.sigdefault);
inheritance.sigmask = some_default_sig_mask;
spawnp(.......);

How do I pass on the signal settings without using spawnp ? Do I use the sigfillset and pthread_procmask functions ? If so, is this syntax correct ? If I just set the sigset variable in sigfillset(), how will the settings get passed on to the process in question ?

fork();
if (child process)
 sigemptyset(sigset)
 sigfillset(sigset)
 pthread_procmask(SIG_SETMASK, some_default_sig_mask, NULL);

Appreciate your help !


You need to effect two things: resetting signal disposition on some signals (SPAWN_SETSIGDEF behavior), and setting the new process's mask (SPAWN_SETSIGMASK behavior).

(Note that you don't actually do the latter in your example posted, but it is plausible that you intended to.)

SPAWN_SETSIGDEF

SPAWN_SETSIGDEF resets the disposition of all signals in the sigdefault set. You can effect this by calling sigaction() on each individual signal you desire to set to default disposition:

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 simply sets the new process's signal mask, which you can do by either pthread_sigmask() or sigprocmask():

By the way, you do not specify SPAWN_SETSIGMASK in your spawnp() snippet, so you're not actually explicitly setting the new process's mask. (It will instead inherit the mask as usual.)

Putting it together

You'll want something like this:

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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜