Как использовать функции sig * set в Linux? - PullRequest
2 голосов
/ 14 июля 2011

Я пытаюсь преобразовать вызов 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? Если да, правильный ли это синтаксис? Если я просто установлю переменную sigset в sigfillset (), как настройки будут переданы рассматриваемому процессу?

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

Ценю вашу помощь!

1 Ответ

1 голос
/ 28 ноября 2011

Необходимо выполнить две вещи: сброс расположения сигналов для некоторых сигналов (поведение 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);
...