发送信号时中断系统调用固定竞争条件 [英] Fixing race condition when sending signal to interrupt system call
问题描述
我有一个线程读取套接字()
s,而我希望能够异步停止线程。线程伪code如下:
I have a thread that read()
s from a socket, and I want to be able to stop the thread asynchronously. The thread pseudocode looks like:
int needs_quit = 0;
void *thread_read(void *arg)
{
while(1)
{
if(needs_quit)
{
close(sock_fd);
return NULL;
}
int ret = read(sock_fd ...);
if(ret == EINTR) //we received an interrupt signal to stop
{
close(sock_fd);
return NULL;
}
//do stuff with read data
}
}
信号处理程序简单地设置 needs_quit
1。在大多数情况下,这code会工作。但是,如果在的信号到达时,如果(needs_quit)
和前阅读(sock_fd ...)
,那么阅读()
不会被打断,线程将永远不会停止。针对此问题最好的解决办法是什么?
The signal handler simply sets needs_quit
to 1. Most of the time, this code will work. But, if a signal arrives after if(needs_quit)
and before read(sock_fd ...)
, then read()
will not be interrupted, and the thread will never stop. What is the best solution for this problem?
我要指出,我设法写与 pthread_cancel可以
工作解决方案,但事实证明,我不能用,由于兼容性问题。
I should point out that I managed to write a working solution with pthread_cancel
, but as it turns out, I'm not allowed to use that due to compatibility issues.
先谢谢您的任何反馈。
推荐答案
当你发现,翻转标志是不够的。还有我能想到的几种方法。
As you discovered, flipping a flag isn't enough. There are several approaches I can think of.
没有标志必要的。
不过, pthread_cancel可以
并不适用于您的环境,正如你提到的,而且许多人认为它容易误操作。
However, pthread_cancel
is not applicable to your environment, as you noted, and many consider it easy to misuse.
守旗,并最低限度耐心。
Keep the flag, and be minimally patient.
更换读
与选择
或调查
用短超时可能是不够好。你关心如果线程退出立即,或在几秒钟内?
Replacing the read
with a select
or poll
with a short timeout may be good enough. Do you care if the thread quits "instantly" or within a few seconds?
没有标志,但仅仅的close()
s或关机
S上的插座,从而唤醒信号处理程序了读
。
No flag, but a signal handler that simply close()
s or shutdown
s the socket and thus wakes up the read
.
关闭FDS可以在多线程环境危险,因为FD可以立即重新使用,另一个线程的打开
或管道
或更多的外来电话。它会是坏的,例如,有信号处理程序接近FD 5,而另一个线程使管道
使用FD 5可读结束,只是你的<$之前C $ C>读。由于@R ..提到,关机
可能会或可能无法正常工作,但是,如果这样做,在这里是安全的。
Closing fds can be dangerous in a multithreaded environment, as the fd can be immediately re-used by another thread's open
or pipe
or more exotic calls. It'd be bad, for instance, to have the signal handler close fd 5 while another thread makes a pipe
using fd 5 for the readable end, just prior to your read
. As @R.. mentions, shutdown
may or may not work, but, if it does, is safe here.
没有标志。相反,你的信号处理程序中的有趣插座和管道的可读结束都在一个字节写入非阻塞管道,以及你的线程选择
秒。如果数据到达(或已经等待)对后者,线程知道它已被发出信号。
No flag. Instead your signal handler writes a byte to a non-blocking pipe, and your thread select
s on both the interesting socket and the readable end of the pipe. If data arrives (or is already waiting) on the latter, the thread knows it has been signalled.
可以使用标志。
有一个功能,原子 PSELECT
周到的信号屏蔽会给你信号传递可靠EINTR迹象。警告:此调用glibc的早期版本是的不的原子
A functional, atomic pselect
and thoughtful signal masking will give you reliable EINTR indications of signal delivery. Warning: early versions of this call in glibc were not atomic.
这篇关于发送信号时中断系统调用固定竞争条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!