2013-04-08 27 views
0

信號是否會中斷主線程,還是從某個操作系統線程調用?換句話說,在執行信號處理程序時,我是否必須擔心線程安全?例如,如果在單獨的線程上調用on_sigint,以下代碼將隨機失敗。他們?會嗎?哪個線程是調用的信號處理程序(例如signal(SIGINT,crtl_c);)?

#include <csignal> 
#include <windows.h> 

HANDLE hSigint; 

void on_sigint(int sig) 
{ 
    if (hSigint != NULL) SetEvent(hSigint); 
    else hSigint = INVALID_HANDLE_VALUE; 
} 

int wmain(int argc, wchar_t** argv) 
{ 
    hSigint = NULL; 
    signal(SIGINT, on_sigint); 
    BuildSomething(); 
    if (hSigint == NULL) 
    { 
     hSigint = CreateEvent(NULL, TRUE, FALSE, NULL); 
     SetSomethingInMotion(); 
     WaitForSingleObject(hSigint, INFINITE); 
    } 
    TearSomethingDown(); 
    return 0; 
} 

儘管有Windows示例,但Linux的答案也很受歡迎。

+0

您使用MSVCRT嗎? – Ben 2013-04-08 16:45:17

+0

我這麼認爲。我正在使用Visual Studio 2012. – 2013-04-08 22:22:42

回答

1

根據文檔,Windows不支持SIGINT。請參閱下文了解更多。

首先,Windows只支持C規範所需的最小信號。

  1. SIGABRT異常終止
  2. SIGFPE浮點錯誤
  3. SIGILL非法指令
  4. SIGINT CTRL + C信號
  5. SIGSEGV非法存儲訪問
  6. SIGTERM終止請求

只有那些信號被支持,並且複雜的交互信號和IO之間的切換不會發生 - 例如SIGINT不會導致正在進行的IO中止,並且SIGALRM不存在。

其次,除了SIGINT所有信號被稱爲這引起了條件相同的線程上。這是因爲MSVCRT使用SEH將這些信號實現爲第一偶然異常,並且SEH異常處理程序在同一個線程上運行。這也意味着,如果你比EXCEPTION_CONTINUE_SEARCH任何其他處理這樣的SEH(如訪問衝突映射到SIGSEGV),則信號函數將不會被調用。

SIGINT另一方面是不支持Win32。等價的功能是SetConsoleCtrlHandler,它總是在不同的線程上調用處理函數。如果您正在使用的CRT如MinGW,Cygwin,或者如果它有效,MSVCRT處理SIGINT,它將始終位於特製的線程上。

如果它是一個僅適用於Windows應用程序中使用SetConsoleCtrlHandler和SEH來代替。

如果你希望做將信號發送到另一個進程的等值金額,您應該GenerateConsoleCtrlEvent做到這一點。

最後,在信號處理程序中通常只有兩件好事 - 退出(無論如何都是默認行爲),或者將消息放入某種隊列中供以後處理(這是最高級別語言是這樣做的,原因很簡單,即使不符合規範,信號在行爲上也是非常不可移植的,並且希望儘可能快地離開處理程序。

+0

嗯,但在Windows中支持SIGINT * *。我剛剛寫了一個成功應用它的應用程序。當我在處理程序中設置斷點時,運行應用程序,然後按Crtl + C,它按預期在處理程序中中斷。 – 2013-04-08 16:12:29

+0

@AnsisMalins,好吧,我錯誤地理解了文檔!我可以告訴你,Ctrl + C由SetConsoleCtrlHandler處理,所以你的CRT必須使用它。我認爲***是*** MSVCRT而不是MinGW或Cygwin? – Ben 2013-04-08 16:41:39

+1

@AnsisMalins,更新了答案。 Ctr + C將始終在單獨的線程中調用。 Ctrl + Break和窗口關閉按鈕(如果它們作爲信號處理)也將在單獨的線程中調用,因爲它們以相同的方式實現。 – Ben 2013-04-08 16:44:59