2014-01-23 31 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