正在取消卡在epoll_wait上的线程
Cancelling thread that is stuck on epoll_wait
我正在用C++和pthreads进行一些事件处理。我有一个从我定义的事件队列中读取内容的主线程,还有一个填充事件队列的辅助线程。队列当然是线程安全的。
工作线程有一个文件描述符列表,并创建一个epoll系统调用来获取这些文件描述符上的事件。它使用epoll_wait来等待fd上的事件。
现在问题来了。假设我想干净地终止我的应用程序,我如何才能正确地取消工作线程?CCD_ 1不是pthread(7)的消除点之一,因此它不能对CCD_。
工作线程main()看起来像这个
while(m_WorkerRunning) {
epoll_wait(m_EpollDescriptor, events, MAXEVENTS, -1);
//handle events and insert to queue
}
当线程启动时,m_WorkerRunning
被设置为true
,并且看起来I可以通过从主线程将m_WorkerRunning
设置为false来中断线程。问题是epoll_wait
理论上可以永远等待。
我想的另一个解决方案是:我可以等待X个时隙,而不是永远等待(-1),然后正确处理无事件的情况,如果m_WorkerRunning == false
,则退出循环并干净地终止工作线程。然后主线程将m_WorkerRunning
设置为false,并休眠X。但是我不确定这种epoll_wait的性能,也不确定什么是正确的X?500毫秒?1秒?10秒?
我想听听一些有经验的建议!
更相关的信息:我正在等待事件的fd是/dev/input
中的设备,所以从技术上讲,我正在做某种输入子系统。目标操作系统是基于ARM架构的Linux(最新内核)。
谢谢!
alk上面的答案几乎是正确的。然而,这种差异是非常危险的。
如果要发送信号以唤醒epoll_wait
0,请不要使用epoll_wait。你必须使用epoll_pwait
,否则你可能会在你的epoll永远不会醒来的情况下参加比赛。
信号异步到达。如果您的SIGUSR1
在检查关闭过程之后到达,但在循环返回epoll_wait
之前到达,则信号不会中断等待(因为没有),但程序也不会退出。
这可能很有可能,也可能极不可能,这取决于循环所花的时间与等待所花时间的关系,但无论如何,这都是一个错误。
alk的答案的另一个问题是,它没有检查为什么等待被中断。这可能有很多原因,有些与你的退出无关。
有关更多信息,请参阅pselect
的手册页。CCD_ 15以类似的方式工作。
此外,永远不要使用kill
向线程发送信号。请改用pthread_kill
。kill
在发送信号时的行为充其量是未定义的。无法保证正确的线程会接收到它,这可能会导致不相关的系统调用中断,或者根本不会发生任何事情。
您可以向线程发送一个信号,该信号将中断对epoll_wait()
的阻塞调用。如果这样做,修改你的代码如下:
while(m_WorkerRunning)
{
int result = epoll_wait(m_EpollDescriptor, events, MAXEVENTS, -1);
if (-1 == result)
{
if (EINTR == errno)
{
/* Handle shutdown request here. */
break;
}
else
{
/* Error handling goes here. */
}
}
/* Handle events and insert to queue. */
}
一种添加信号处理程序的方法:
#include <signal.h>
/* A generic signal handler doing nothing */
void signal_handler(int sig)
{
sig = sig; /* Cheat compiler to not give a warning about an unused variable. */
}
/* Wrapper to set a signal handler */
int signal_handler_set(int sig, void (*sa_handler)(int))
{
struct sigaction sa = {0};
sa.sa_handler = sa_handler;
return sigaction(sig, &sa, NULL);
}
要为信号pthread_cancel
0设置此处理程序,请执行以下操作:
if (-1 == signal_handler_set(SIGUSR1, signal_handler))
{
perror("signal_handler_set() failed");
}
从另一个进程发送信号SIGUSR1
:
if (-1 == kill(<target process' pid>, SIGUSR1))
{
perror("kill() failed");
}
让进程向自身发送信号:
if (-1 == raise(SIGUSR1))
{
perror("raise() failed");
}
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- future::wait() 是否与 async() 执行线程的完成同步?
- 线程锁定互斥锁的速度比 std::conditional_variable::wait() 快
- std::condition_variable::wait()是POSIX线程取消点吗
- 在 std::future 上多次从多个线程调用 wait() 是否安全
- 用于线程"Wait for Alert/Event"的标准库版本