【问题标题】:c - How to handle SIGPIPE in a multithreaded environment?c - 如何在多线程环境中处理 SIGPIPE?
【发布时间】:2014-05-27 12:08:36
【问题描述】:

我有一个用 C 编写的多线程 SSL 服务器,其行为如下:

  • 主线程等待客户端请求 (epoll),接受它们并为每个客户端套接字生成一个分离的线程
  • 每个线程单独执行SSL_accept。 SSL 握手 成功后,线程会接收来自客户端的消息,并为每个 SSL_read 回复一条消息。
  • 当客户端关闭套接字或发生任何错误时,客户端线程退出。

我尝试模拟并发客户端连接来测试服务器。

在一次这样的模拟中,我的服务器以SIGPIPE 信号退出。

有没有办法在线程级别捕获和处理SIGPIPE?我希望各个线程处理信号,而不是整个进程退出。

最初我尝试signal(SIGPIPE,SIG_IGN),但signal(2) man 说:

未指定多线程进程中 signal() 的效果。

signalfd可以用来处理这样的SIGPIPEs吗? 还是有其他解决方案?

注意:服务器在 Ubuntu 12.04 上运行,我不能在 send 上使用 MSG_NOSIGNAL,因为我直接使用 OpenSSL 作为库(无源代码)

提前致谢。

【问题讨论】:

  • 没有。那篇文章没有谈到多线程环境。我已经尝试过该帖子中提到的选项。
  • 它可能是未指定的,但如果你在创建线程之前这样做,你不会有问题。忽略信号很容易。
  • 所以?这仍然是正确的答案。
  • 我在 SIGPIPE 上为每个新线程尝试了 SIG_IGN。它没有帮助我。在创建任何线程之前执行 signal(SIGPIPE,SIG_IGN) 有帮助吗?

标签: c linux multithreading signals


【解决方案1】:

有没有办法在线程级别捕获和处理 SIGPIPE?我希望各个线程处理信号,而不是整个进程退出。

是的,有。您需要在除一个线程之外的所有线程中阻止信号(最好在创建任何线程之前执行此操作)。如果您使用的是 pthreads,则可以使用 pthread_sigmask,因为这将保证,在调用它之后,每个创建的线程都将继承信号掩码。然后在一个特定线程中,您需要使用sigaction 注册一个处理程序(不要使用signal,它已过时)。

当信号到达您的进程时,它将被阻塞,直到这个线程将继续它在进程上工作(只有这样信号才被进程接收,这就是为什么它是未指定的行为 - 它取决于哪个线程正在运行,但通过阻塞信号在所有其他线程上,您指定哪个线程可以对其做出反应)。

其他方式:

如果你不想永远接收到这个信号并知道哪个套接字被它破坏了,你只能使用pthread_sigmask 并忽略所有线程的这个信号。然后函数,由于 SIGPIPE 而中断应该返回 -1 (我不熟悉 openssl,但是当涉及到套接字时,这是write 的说法,套接字在另一侧关闭)。

【讨论】:

  • 谢谢。如果我的解释是正确的,您是否建议我有一个专用线程来处理所有其他线程上的信号和阻塞信号?但是我如何找到 SIGPIPE 是针对哪个线程提出的?我需要正确关闭客户端套接字(导致 SIGPIPE)并退出该特定线程。
  • 我对所有线程都使用了pthread_sigmask 并忽略了SIGPIPE。到目前为止,我还没有看到任何异常退出。跑了几个测试。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 2012-10-08
  • 2020-07-04
相关资源
最近更新 更多