О неоднозначном описании sigwait () - PullRequest
15 голосов
/ 13 июня 2011

Если во время вызова нет ожидающего сигнала в наборе, поток должен быть приостановлен до тех пор, пока один или несколько не станут ожидающими.Сигналы, определенные set, должны быть заблокированы во время вызова sigwait ();в противном случае поведение не определено.Влияние sigwait () на действия сигналов для сигналов в наборе не определено.

Это действительно неоднозначно, в чем разница между pending и block здесь?

И его вывод о том, как выбирать между sigwait и sigaction, совершенно не ясен:

Таким образом, когда необходимо выполнить код в ответ на асинхронный сигнал для уведомленияthread, sigwait () должен использоваться для обработки сигнала.В качестве альтернативы, если реализация предоставляет семафоры, их также можно использовать либо после sigwait (), либо из подпрограммы обработки сигналов, ранее зарегистрированной в sigaction ().

Может кто-то объяснить причинуsigwait более рационально?

Ответы [ 2 ]

22 голосов
/ 13 июня 2011

Каждый процесс имеет так называемую маску сигналов , связанную с ним, которая определяет набор сигналов, которые заблокированы . Сигнальная маска может быть запрошена или установлена ​​с помощью setprocmask(2) (для однопоточного кода) и pthread_sigmask(3) (для многопоточного кода).

Всякий раз, когда сигнал повышается (либо явно через kill(2) или raise(3), либо через какой-либо другой механизм, такой как повышение ошибки сегментации SIGSEGV), сигнал проверяется по текущей маске сигнала. Если сигнал не заблокирован, то на него воздействуют немедленно: соответствующий обработчик сигнала вызывается, если он установлен, в противном случае выполняется действие по умолчанию (обычно выход с ненормальным состоянием или его игнорирование). Если сигнал блокируется маской сигнала, то состояние сигнала устанавливается на в ожидании , и программа продолжает выполнение.

Итак, рассмотрим следующий пример программы:

#include <signal.h>
#include <stdio.h>

void on_sigusr1(int sig)
{
  // Note: Normally, it's not safe to call almost all library functions in a
  // signal handler, since the signal may have been received in a middle of a
  // call to that function.
  printf("SIGUSR1 received!\n");
}

int main(void)
{
  // Set a signal handler for SIGUSR1
  signal(SIGUSR1, &on_sigusr1);

  // At program startup, SIGUSR1 is neither blocked nor pending, so raising it
  // will call the signal handler
  raise(SIGUSR1);

  // Now let's block SIGUSR1
  sigset_t sigset;
  sigemptyset(&sigset);
  sigaddset(&sigset, SIGUSR1);
  sigprocmask(SIG_BLOCK, &sigset, NULL);

  // SIGUSR1 is now blocked, raising it will not call the signal handler
  printf("About to raise SIGUSR1\n");
  raise(SIGUSR1);
  printf("After raising SIGUSR1\n");

  // SIGUSR1 is now blocked and pending -- this call to sigwait will return
  // immediately
  int sig;
  int result = sigwait(&sigset, &sig);
  if(result == 0)
    printf("sigwait got signal: %d\n", sig);

  // SIGUSR1 is now no longer pending (but still blocked).  Raise it again and
  // unblock it
  raise(SIGUSR1);
  printf("About to unblock SIGUSR1\n");
  sigprocmask(SIG_UNBLOCK, &sigset, NULL);
  printf("Unblocked SIGUSR1\n");

  return 0;
}

Выход:

SIGUSR1 received!
About to raise SIGUSR1
After raising SIGUSR1
sigwait got signal: 30
About to unblock SIGUSR1
SIGUSR1 received!
Unblocked SIGUSR1
4 голосов
/ 13 июня 2011

со страницы руководства signal(7):

Signal Mask and Pending Signals
    A  signal  may  be  blocked,  which means that it will not be delivered
    until it is later unblocked.  Between the time when it is generated and
    when it is delivered a signal is said to be pending.

"Ожидание" и "заблокировано" не являются взаимоисключающими.

Также из signal(7)Страница man:

Synchronously Accepting a Signal
    Rather than asynchronously catching a signal via a signal  handler,  it
    is  possible to synchronously accept the signal, that is, to block exe-
    cution until the signal is delivered, at which point the kernel returns
    information about the signal to the caller.  There are two general ways
    to do this:

    * sigwaitinfo(2), sigtimedwait(2),  and  sigwait(3)  suspend  execution
      until  one  of  the signals in a specified set is delivered.  Each of
      these calls returns information about the delivered signal.

Таким образом, sigaction() используется для разрешения выполнения другого кода до тех пор, пока сигнал не будет ожидающим, тогда как sigwait() приостанавливает выполнение потока до тех пор, пока сигнал не будет ожидающимно заблокирован.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...