Пробуждение потока из обработчика сигнала

Я понимаю, что единственное, что разрешено делать обработчику сигналов в 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() в обработчике сигналов (поправьте меня, если я ошибаюсь)
  2. Сигнал может прийти только между проверкой doWait и когда поток переходит в спящий режим, он никогда не проснется (очевидно, я не могу заблокировать мьютекс в signalHander, чтобы избежать этого).

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

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

6

Решение

Предполагая, что стандартная библиотека вашего поставщика использует 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, так далее.).

5

Другие решения


По вопросам рекламы [email protected]