Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C POSIX线程/信号:确定信号发送到哪个线程的便携式方法?_C_Multithreading_Posix_Signals - Fatal编程技术网

C POSIX线程/信号:确定信号发送到哪个线程的便携式方法?

C POSIX线程/信号:确定信号发送到哪个线程的便携式方法?,c,multithreading,posix,signals,C,Multithreading,Posix,Signals,我有一个多线程服务器(使用POSIX线程),每个持久连接有一个线程。在其中一个线程中,连接的另一端关闭,从而导致交付SIGPIPE。是否有一个(最好是可移植的)来确定发生这种情况的线程(以及哪个连接),这样我就可以让我的信号处理程序自己执行线程/连接清理工作,或者设置一个标志,以便主线程和工作线程分别看到它们以后需要执行此操作 编辑:我想知道是否可以使用&errno,将其存储在全局数组中,并将其与线程的服务器标识符关联,然后在信号处理程序中搜索&errno。信号处理程序是否可以看到线程的特定er

我有一个多线程服务器(使用POSIX线程),每个持久连接有一个线程。在其中一个线程中,连接的另一端关闭,从而导致交付SIGPIPE。是否有一个(最好是可移植的)来确定发生这种情况的线程(以及哪个连接),这样我就可以让我的信号处理程序自己执行线程/连接清理工作,或者设置一个标志,以便主线程和工作线程分别看到它们以后需要执行此操作


编辑:我想知道是否可以使用&errno,将其存储在全局数组中,并将其与线程的服务器标识符关联,然后在信号处理程序中搜索&errno。信号处理程序是否可以看到线程的特定errno?我对threadsafe errno是如何工作的理解是大致的吗?

我不这么认为,不。多线程服务器的更好解决方案是抑制
SIGPIPE
信号(通过调用
signal(SIGPIPE,SIG_IGN)
作为程序启动例程的一部分),然后让线程处理错误值(-1/EPIPE)而是由
send()
返回


信号和多线程不能很好地混合。

我的方法是让SIGPIPE的信号处理程序将其线程ID写入一个全局变量,并使用其他机制将其发送给线程,该线程应该处理它。

使用一个全局变量(声明的线程本地)来存储线程ID怎么样,在创建线程时初始化它,并在线程的信号处理程序中引用它

有关此方面的GCC详细信息,请参见此处:或更一般的此处:

您可以在信号处理程序中安全使用。是的

这个答案是留给后代的。从技术上讲,我不推荐这种方法。其他答案和评论建议采用不同的方法,因此更适合实施

在提出这个问题时,
pthread\u self
的安全性并不一定很明显。2013年发布的POSIX:2008技术勘误表1(在该问题提出两年后)澄清了
pthread_self
是明确的异步信号安全的,如表中所述


与此相关的是,您在评论中提到,您不确定“内核是否将[SIGPIPE]发送到任何未被阻止的线程”。这是一个很好的问题——它是进程导向的信号还是线程导向的信号谢天谢地,这是错的。内核生成的SIGPIPE是响应某个I/O调用的“同步生成”信号,并发送给调用线程。POSIX:2001勘误表2(2004)明确阐明了这一点,即针对
写入
的SIGPIPE是(增加了强调)。

我考虑过这种可能性;问题是,直到下一次我需要通过该连接发送数据时,我才检测到断开连接——这可能永远都不会发生。通过在fd上选择“仅错误”ymmm,可以很容易地发现这一点,你是对的。我正在使用epoll,但忘记了EPOLLHUP。我想您会发现“在下次我需要发送数据到该连接之前不会检测到断开连接”问题是一个单独的问题,无论您是否使用信号,您都必须处理它。根据主机的TCP keepalive选项的设置,TCP默认情况下不会检测到空闲连接已被切断很长时间(如果有)。在某些操作系统(如Linux)上,您可以基于每个套接字设置keepalive选项(通过setsockopt(fd、SOL_TCP、TCP_KEEPIDLE),而在其他操作系统上(Windows)这是一个单一的全局设置。这是正确的-所有网络服务器,而不仅仅是多线程服务器,都应该忽略
SIGPIPE
,而是处理
EPIPE
。@SteelyDan:
SIGPIPE
不会比
EPIPE
更及时地交付-信号只会在
EPI的同一时间生成PE
return否则会发生。这仍然提出了一个基本问题,即我必须以何种可移植的、信号安全的方式找出发生这种情况的特定线程,因为我必须找出线程ID。这非常简单:例如,通过系统支持的任何事件机制引发事件(包括向管道发送内容)并让线程侦听这些事件(包括在该管道上选择),读取(锁保护)如果有必要,请使用全局变量,并处理itI我认为全局变量方法的一个问题是,如果两个信号快速连续发出——第二个信号可能会在第一个处理程序执行之前覆盖第一个信号写入的值。您至少需要一个锁保护的FIFO队列……但随后会遇到second问题,即不允许您从信号处理程序内部锁定互斥。恐怕我不确定我是否理解您的建议。您是说信号处理程序向事件管理线程发送了一些内容,然后在事件管理线程上接收到它的哪个特定管道知道事件通知来自哪个线程?我曾考虑过一种本质上类似的体系结构,但回避了它,因为它需要每个连接三个文件描述符(一个用于套接字,另两个用于管道两端),这比我想象的要快得多。(针对Eugen Rieck)@SteelyDan,取决于你对“便携式”的定义是的,有可能没有更简单的方法。最便携的方法是管道,但您确实意识到,您不需要一直连接到管道-只需在接收到信号后连接即可!如果信号发送到特定线程,则该线程将处理该信号。这就是向特定线程发送信号的含义我不明白要检查什么?因为那不告诉我