2014-01-23 27 views
0

我的信号SIGTERM和SIGINT的信号处理程序在接收到任一信号时会导致轮询错误。我不确定它为什么这样做,我想我不知道我错过了一些sigaction的行为。C++任何信号的轮询错误

while(!signalHandler.gotExitSignal()) { 
    switch (poll(&ufds[0], NUM_FDS, POLL_TIMEOUT)) { 
     case -1: { 
      throw std::runtime_error("poll error (-1)"); /* ABORT */ 
     } 
     . 
     . 

我的signalHandler是一个包含sigaction处理的类。

struct sigaction killAction, termAction; 

memset(&killAction, 0, sizeof(struct sigaction)); 
killAction.sa_handler = SignalHandler::ExitHandler; 
sigemptyset(&killAction.sa_mask); 
killAction.sa_flags = 0; 
if(sigaction(SIGTERM, &killAction, NULL) < 0) 
    throw SignalException("sigaction failed for killAction"); 

memset(&termAction, 0, sizeof(struct sigaction)); 
termAction.sa_handler = SignalHandler::ExitHandler; 
sigemptyset(&termAction.sa_mask); 
termAction.sa_flags = 0; 
if(sigaction(SIGTERM, &termAction, NULL) < 0) 
    throw SignalException("sigaction failed for termAction"); 

所以我的预期片断循环的行为,我给了应该是:(!signalHandler.gotExitSignal())

  1. 而{
  2. 开关(轮询(&个UFD [0],NUM_FDS ,POLL_TIMEOUT)){
  3. 投票后做一些清理的东西
  4. 转到1个
  5. 而(!signalHandler.gotExitSignal( )){
  6. INTERRUPT
  7. 开关(轮询(&个UFD [0],NUM_FDS,POLL_TIMEOUT)){
  8. 做一些清理东西轮询之后
  9. 转到第1
  10. 分段环

什么使用:

  1. while(!signalHandler.gotExitSignal()){
  2. 开关(轮询(&个UFD [0],NUM_FDS,POLL_TIMEOUT)){
  3. 轮询后做一些清理东西
  4. 转到第1个
  5. 而(!signalHandler.gotExitSignal()){
  6. INTERRUPT
  7. throw std :: runtime_error(“poll error(-1)”);

我试过一个场景,轮询开关后,我睡了2秒,然后终止程序 - 它优雅地退出循环条件。当我轮询并接收信号时存在问题。我没有使用SIGHUP信号,它用于告诉程序重新加载它的配置,但是我为SIGHUP设置了一个信号来测试它,并且像我的其他信号一样通过轮询错误终止了我的程序。但是我不能让我的程序在任何信号上崩溃,我想知道我是否忘记了一些东西。

+0

由于信号可能已经中断了对被调查的fds的任何操作,poll()应该用-1(这个开关在结果BTW上相当无用)和errno EINTR解救出来。与您的信号处理器定义无关。 –

回答

5

这是预期的。在poll()中阻塞并且信号到达时,轮询将失败,并且errno将被设置为EINTR。对于大多数系统调用,您将获得相同的行为。

你可以和应该检测这个(你现在打出来投票循环迟早也一样,民意调查()将返回 当信号被捕获。)

while(!signalHandler.gotExitSignal()) { 
    switch (poll(&ufds[0], NUM_FDS, POLL_TIMEOUT)) { 
     case -1: { 
      if (errno == EINTR) { 
       continue; 
      } 
      throw std::runtime_error("poll error (-1)"); /* ABORT */ 
     } 

你最有可能想设置sigaction的标志也是SA_RESTART

killAction.sa_flags = SA_RESTART; 

这将导致大多数系统调用在信号被捕获时不返回错误。有关详细信息,请阅读sigaction()的手册页,并阅读man 7 signal中的“信号处理程序中的系统调用和库函数中断”部分。

值得注意的是,无论如何设置SA_RESTART标志,poll()仍将被信号中断(立即返回错误)。

+0

什么是大量的信息。不胜感激。 – user2843645