2015-06-29 4 views
5

Я понимаю, что единственное, что может сделать обработчик сигналов в ISO/C++ 11, - это читать или записывать в блокирующую свободную атомную переменную или volatile sig_atomic_t (я считаю, POSIX немного более разрешительный и позволяет называть кучу системных функций).Пробуждение потока от обработчика сигнала

Мне было интересно, если есть какой-либо способ, просыпаться поток, который ждет переменную условия. То есть что-то вроде:

#include <mutex> 
#include <atomic> 
#include <condition_variable> 


std::mutex mux; 
std::condition_variable cv; 

std::atomic_bool doWait{ true }; 

void signalHandler(int){ 
    doWait = false; 
    cv.notify_one(); 
} 

int main() { 
    //register signal handler 
    //Do some stuff 

    {//wait until signal arrived 
     std::unique_lock<std::mutex> ul(mux); 
     cv.wait(ul, []{return !doWait; }); 
    } 

    //Do some more stuff 
} 

, который имеет по крайней мере две проблемы:

  1. Я считаю, что я не разрешается называть notify_one() в обработчике сигнала (corrct меня, если я ошибаюсь)
  2. Сигнал мог поступать как раз между проверкой на doWait, и когда нить идет спать, поэтому она никогда не проснется (очевидно, я не могу заблокировать мьютекс в сигнале Хандера, чтобы этого избежать).

До сих пор единственным решением, я могу видеть это реализовать занят ожидания на переменной doWait (вероятно, спать в течение нескольких миллисекунд в каждой итерации), который поражает меня как весьма неэффективно.

Обратите внимание, что хотя моя программа выше имеет только один поток, я назвал свой вопрос многопоточным, потому что речь идет о примитивах управления потоками. Если в стандартном C++ нет решения, я бы согласился принять решение с использованием конкретных функций Linux/POSIX.

ответ

5

Предполагая, что стандартная библиотека вашего поставщика использует pthread_cond_* функции для реализации C++ 11 переменных условий (libstdC++ и LibC++ это сделать), то pthread_cond_* функция не является асинхронным сигналом безопасности, чтобы не может быть вызвана из обработчика сигналу.

http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cond_broadcast.html От:

Это не безопасно использовать функцию pthread_cond_signal() в обработчике сигнала, который вызывается асинхронно. Даже если бы это было безопасно, между тестом boolean pthread_cond_wait(), который не может быть эффективно устранен, по-прежнему будет проходить гонка.

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

Если вам удобно использовать семафоры, sem_post обозначен как async-signal-safe. В противном случае ваши варианты обработки сигналов являются обычными: классический самоходный канал, поток обработки сигналов, заблокированный на sigwait/sigwaitinfo, или на платформе (Linux signalfd и т. Д.).

+0

Спасибо. Этого я боялся (хотя я не знал полного списка доступных механизмов Linux/Posix). Я очень надеюсь, что однажды мы сможем получить семафоры в стандарт. – MikeMB

Смежные вопросы