我有一个多线程应用程序,需要在中断,终止等信号下正常停止它。
这里有一个片段来说明逻辑的相关部分。
std::atomic_bool running = true;
std::mutex mutex;
std::condition_variable condition;
void signal_handler(int signal)
{
// in another thread `[&]() { return !running || something_to_do_conditon; } == false`
// what means continue to wait
running = false;
condition.notify_one();
// another thread goes to sleep
}
void run() {
while(true) {
std::unique_lock lock(mutex);
condition.wait_for(lock, std::chrono::hours(1), [&]() { return !running || something_to_do_conditon; });
if (!running) {
return;
}
// do smth
}
}
int main()
{
// Install a signal handler
std::signal(SIGINT, signal_handler);
std::signal(SIGTERM, signal_handler);
std::thread thread(run);
thread.join();
}
正如您在signal_handler
中所看到的那样,甚至可能将running
设置为false
的情况下,condition
仍被告知还有一个场景(用在线注释)线程进入睡眠状态1个小时。发生这种情况是因为running
变量周围没有互斥量。这允许线程锁定互斥对象,并在设置变量之前检查条件。如果我添加类似的内容
{
std::lock_guard<std::mutex> lock(mutex);
running = false;
}
在应避免的处理程序中。
然后,问题是如何使用互斥锁(是否有可能)而不会导致潜在的死锁或任何其他问题。还有其他技巧可以削弱信号中的休眠线程。
答案 0 :(得分:2)
在pthreads程序中处理信号的可靠方法是屏蔽每个线程中希望处理的所有信号,并创建一个专用的信号处理线程,该线程循环调用sigwaitinfo()
(或sigtimedwait()
)。
然后,信号处理线程可以使用受互斥锁保护的普通共享变量和pthread_cond_signal()
/ pthread_cond_broadcast()
唤醒来通知其他线程接收到的信号。
在您的示例中,专用信号处理线程可以在更改running
标志之前安全地锁定互斥锁,因为它只是在普通线程上下文中,而不是信号处理程序。