2

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

あなたの助けに感謝 !

4

1 に答える 1

1

一部の信号の信号処理をリセットすること(SPAWN_SETSIGDEFの動作)と、新しいプロセスのマスクを設定すること(SPAWN_SETSIGMASKの動作)の2つを実行する必要があります。

(投稿された例では実際には後者を実行していないことに注意してください。ただし、意図したことはもっともらしいです。)

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);
于 2011-11-28T14:06:12.747 に答える