CentOS 上的“信号”功能:意外行为

Posted

技术标签:

【中文标题】CentOS 上的“信号”功能:意外行为【英文标题】:`signal` function on CentOS: unexpected behavior 【发布时间】:2014-08-13 07:03:55 【问题描述】:

我需要在 CentOS 应用程序上禁用SIGPIPE,因为当我的应用程序在不稳定的 Internet 连接下工作时,这个信号会使我的应用程序崩溃。 我在main 函数中使用以下代码:

signal(SIGPIPE, SIG_IGN);

但是,程序仍然会因SIGPIPE 而崩溃。是什么原因?我必须在每个线程上调用这个函数,还是调用main 函数就足够了,程序会全局忽略SIGPIPE?如果不需要在每个线程上调用它,为什么SIGPIPE 应该忽略信号仍然会使程序崩溃?

【问题讨论】:

在多线程应用程序中,您不应使用 signal 而应使用 sigaction。阅读here了解更多详情 【参考方案1】:

这是一个代码示例,可让您在 linux 上设置自己的信号处理程序,捕获 SIGPIPE 并用它做一些事情。

#include <signal.h>
#include <unistd.h>
#include <cerrno>
#include <system_error>
#include <iostream>

static sigset_t theMask;
static int count = 0;

static void
signalWrapper(
    int         theSignalNumber,
    siginfo_t*  theSignalDescription,
    void*       theUserContext)

  // Do something here as reaction to you SIGPIPE
  // This is better way to react on such things

  std::cout << "Got signal " << theSignalNumber << std::endl;

  // Reinstall handler
  struct ::sigaction sa;
  sa.sa_sigaction = &signalWrapper;
  sa.sa_mask = theMask;
  sa.sa_flags = SA_SIGINFO;

  try
  
    if (::sigaction(theSignalNumber, &sa, NULL) == -1)
      throw std::error_code(errno, std::system_category());
  
  catch (const std::error_code& ec)
  
    std::cerr << ec << std::endl;
  

  count++;


void
setupSignalHandlers()

  struct ::sigaction sa;

  // Prepare mask
  sigemptyset(&theMask);
  sigaddset(&theMask, SIGPIPE);
  // Add some more if you need it to process

  sa.sa_mask      = theMask;
  sa.sa_flags     = SA_SIGINFO;
  sa.sa_sigaction = &signalWrapper;

  // Perform setup
  try
  
    if (::sigaction(SIGPIPE, &sa, NULL) == -1)
      throw std::error_code(errno, std::system_category());
  
  catch (const std::error_code& ec)
  
    std::cerr << ec << std::endl;
  


int
main()

  std::cout << "Set handler!" << std::endl;
  setupSignalHandlers();

  std::cout << "Emit 5 SIGPIPE signals" << std::endl;
  while (count < 5)
  
    kill(getpid(), SIGPIPE);
    usleep(100);
  

  return 0;

和输出:

Set handler!
Emit 5 SIGPIPE signals
Got signal 13
Got signal 13
Got signal 13
Got signal 13
Got signal 13

我提供信号处理程序,因为处理破坏应用程序的信号比忽略它更正确。也许您需要重新建立连接或做一些其他事情。

【讨论】:

【参考方案2】:

根据 Signal(2) 的手册页,“未指定多线程进程中 signal() 的影响。”您可以尝试确保在创建任何其他线程之前在主线程中调用 signal(),但不能保证它可以正常工作。

无论如何,signal() 已被弃用,所以我建议切换到 sigaction()。我一直在多线程应用程序中使用它,没有任何问题。

【讨论】:

以上是关于CentOS 上的“信号”功能:意外行为的主要内容,如果未能解决你的问题,请参考以下文章

明确地监听信号

OS X 上的奇数/错误 sem_getvalue 信号量行为

奇怪的 POSIX 信号量行为(卡在 Linux 上的 sem_wait 上)

定义 QML 信号参数类型时出现意外的 Token `:'

致命信号 16 (SIGSTKFLT) 意外发生

Qt 应用程序在分叉到后台时意外收到 HUP 信号