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

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

signal(SIGPIPE, SIG_IGN);

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

【问题讨论】:

  • 在多线程应用程序中,您不应使用 signal 而应使用 sigaction。阅读here了解更多详情

标签: c++ multithreading sockets signals signal-processing


【解决方案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()。我一直在多线程应用程序中使用它,没有任何问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      相关资源
      最近更新 更多