Я понимаю, что единственное, что разрешено делать обработчику сигналов в 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
}
У которого есть как минимум две проблемы:
notify_one()
в обработчике сигналов (поправьте меня, если я ошибаюсь)doWait
и когда поток переходит в спящий режим, он никогда не проснется (очевидно, я не могу заблокировать мьютекс в signalHander, чтобы избежать этого). Пока что единственное решение, которое я вижу, это реализовать занятое ожидание на doWait
переменная (вероятно, спит в течение нескольких миллисекунд в каждой итерации), что мне кажется довольно неэффективным.
Обратите внимание, что, хотя моя программа выше имеет только один поток, я обозначил свой вопрос как многопоточность, потому что речь идет о примитивах управления потоками. Если в стандарте c ++ нет решения, я бы согласился принять решение, используя специальные функции Linux / POSIX.
Предполагая, что стандартная библиотека вашего поставщика использует 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
обозначен как асинхронный сигнал-безопасный. В противном случае ваши варианты обработки сигналов являются обычными: классический self-pipe, поток обработки сигналов заблокирован sigwait
/sigwaitinfo
или специфичные для платформы средства (Linux signalfd
, так далее.).