sigwait в Linux (Fedora 13) против OS X - PullRequest
2 голосов
/ 03 июня 2010

Поэтому я пытаюсь создать обработчик сигнала, используя pthreads, который работает как в OS X, так и в Linux. Приведенный ниже код работает на OS X, но не работает на Fedora 13.

Приложение довольно простое. Он порождает pthread, регистрирует SIGHUP и ждет сигнала. После вызова обработчика сигнала я блокирую SIGHUP в главном потоке, поэтому сигнал должен отправляться только в поток signal_handler.

В OS X это работает нормально, если я компилирую, запускаю и отправляю SIGHUP процессу, который печатает "Got SIGHUP". В Linux это просто убивает процесс (и печатает Hangup). Если я закомментирую signal_handler pthread_create, приложение не умрет.

Я знаю, что приложение попадает в sigwait и блокирует, но вместо того, чтобы возвращать код сигнала, оно просто убивает приложение.

Я выполнил тест, используя следующие команды:

g++ test.cc -lpthread -o test
./test &
PID="$!"
sleep 1
kill -1 "$PID"

test.cc

#include <pthread.h>
#include <signal.h>
#include <iostream>

using namespace std;

void *signal_handler(void *arg) {
  int sig;
  sigset_t set;

  sigemptyset(&set);
  sigaddset(&set, SIGHUP);

  while (true) {
    cout << "Wait for signal" << endl;
    sigwait(&set, &sig);
    if (sig == SIGHUP) {
      cout << "Got SIGHUP" << endl;
    }
  }
}

int main() {
  pthread_t handler;
  sigset_t set;

  // Create signal handler
  pthread_create(&handler, NULL, signal_handler, NULL);

  // Ignore SIGHUP in main thread
  sigfillset(&set);
  sigaddset(&set, SIGHUP);
  pthread_sigmask(SIG_BLOCK, &set, NULL);

  for (int i = 1; i < 5; i++) {
    cout << "Sleeping..." << endl;
    sleep(1);
  }

  pthread_join(handler, NULL);
  return 0;
}

1 Ответ

3 голосов
/ 03 июня 2010

Спецификация POSIX для sigwait() говорит:

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

Ты этого не делаешь. Если вы добавите:

pthread_sigmask(SIG_BLOCK, &set, NULL);

к вашей функции signal_handler() сразу после sigaddset(), тогда она работает правильно.

...