Подтвердить что ты не робот

О двусмысленном описании sigwait()

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

void on_sigusr1(int sig)
{
  // Note: Normally, it 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 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

Ответ 2

На странице signal(7) man:

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

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() приостанавливает выполнение потока до тех пор, пока сигнал не будет отложен, но будет заблокирован.