发送信号时中断系统调用固定竞争条件 [英] Fixing race condition when sending signal to interrupt system call

查看:146
本文介绍了发送信号时中断系统调用固定竞争条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个线程读取套接字() 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 shutdowns 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 selects 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆