2015-05-28 72 views
2

我有在XCode 6中構建的控制檯C++應用程序,並且想要爲其添加SIGTERM處理程序。有很多例子,但我無法讓他們工作。在OSx中處理sigterm

#include <csignal> 

namespace 
{ 
    volatile std::sig_atomic_t gDone = 0; 
} 

static void term_handler(int i) 
{ 
    gDone = 1; 
} 

int main(int argc, const char * argv[]) 
{ 
    std::signal(SIGTERM, term_handler); 
    while (!gDone); 
    return 0; 
} 

調試器停在while聲明,但處理不叫。與此代碼相同的問題

#include <signal.h> 

volatile sig_atomic_t gDone = 0; 

void term_handler(int i) 
{ 
    gDone = 1; 
} 

int main(int argc, char* argv[]) 
{ 
    struct sigaction sa; 
    sigset_t newset; 
    sigemptyset(&newset); 
    sigaddset(&newset, SIGHUP); 
    sigprocmask(SIG_BLOCK, &newset, 0); 
    sa.sa_handler = term_handler; 
    sigaction(SIGTERM, &sa, 0); 

    while(!gDone); 
    return 0; 
} 

是否存在代碼問題?在OSX中處理信號的正確方法是什麼?

+1

你是如何傳遞信號的? – jxh

+0

@jxh使用「kill」。問題在於XCode中斷了週期的執行,實際上顯示了執行被SIGTERM中斷的消息。但處理程序不會被調用。 – Sergi0

+0

你可以把斷點放在'return'而不是'while'嗎?我不確定什麼打破'while'購買你。 – jxh

回答

1

OK,我現在在家和我的Mac上工作。再一次,你的代碼(第二個示例)已經證明很好。這個確認是在終端上用gcc和「kill -TERM」完成的。源代表SIGTERM,與正常一樣,但是kill(在OS X上)指向TERM。您看到的XCode暫停是由於XCode造成的,而不是您的代碼。我嘗試了兩種方法,Terminal和XCode。但是,我找不到抑制這種中斷的先例。

只是在這裏重點...你問,代碼有問題嗎?答:不,您問,在OSX中處理信號的正確方法是什麼?答案:你已經這樣做了。新問題:當信號發生時,如何讓XCode(lldb)不會暫停?答案:How to tell LLDB debugger not to handle SIGBUS?

+0

(un?)的donjuedo鏈接,幸運的是,在調試器會話中,處理程序不起作用,導致調試器截獲信號。 – Sergi0

+0

我認爲你仍然可以做到這一點。當我看着「man lldb」時,我看到提到了lldb啓動時讀取的3個文件。我已經使用.gdbinit文件與gdb設置斷點等,節省我手動設置每個調試會話。所以我敢打賭,如果你定製了上面提到的你的SIGTERM的stackoverflow答案,你可以把這個命令放在lldb的init文件中,XCode會調用lldb並按你的意願行事。我認爲。 – donjuedo

1

你的代碼沒問題。殺死:

kill -SIGTERM 31573 

因爲

kill -9 31573 

其中31573是我的進程ID,沒有正常退出。我在代碼中添加了一個printf,告訴我它正在退出。

+0

糟糕。我在Ubuntu上做了這個工作,而不是我剛剛注意到的OS X。現在我越過我的手指,答案也適用於你。 – donjuedo

+0

'kill -9'完全不等於'kill -SIGTERM',這就是爲什麼你的進程沒有用'kill -9'優雅地退出。 'SIGKILL',a.k.a.信號編號9,不能被捕獲。 'SIGTERM'通常是Linux上的信號15 - 不知道OSX是否命令他們的信號不同或者不... – twalberg

+0

你是對的。我責備死記硬背(我自己的死記硬背)。 – donjuedo

1

發送信號並且調試器停止後,您必須繼續到達信號處理程序中的斷點。

(lldb) break set -n term_handler 
Breakpoint 1: where = a.out`term_handler(int) + 4 at sig.cc:11, address = 0x0000000100000f54 
(lldb) run 
Process 42532 launched: './a.out' (x86_64) 
Process 42532 stopped 
* thread #1: tid = 0x18dc39, 0x0000000100000f30 a.out`main(argc=15, argv=0x00007fff5fbffb58) + 32 at sig.cc:17, queue = 'com.apple.main-thread', stop reason = signal SIGTERM 
    frame #0: 0x0000000100000f30 a.out`main(argc=15, argv=0x00007fff5fbffb58) + 32 at sig.cc:17 
    14 int main(int argc, const char * argv[]) 
    15 { 
    16  std::signal(SIGTERM, term_handler); 
-> 17  while (!gDone); 
    18  std::puts("done!"); 
    19  return 0; 
    20 } 
(lldb) c 
Process 42532 resuming 
Process 42532 stopped 
* thread #1: tid = 0x18dc39, 0x0000000100000f54 a.out`term_handler(i=15) + 4 at sig.cc:11, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 
    frame #0: 0x0000000100000f54 a.out`term_handler(i=15) + 4 at sig.cc:11 
    8  
    9 static void term_handler(int i) 
    10 { 
-> 11  gDone = 1; 
    12 } 
    13 
    14 int main(int argc, const char * argv[]) 
(lldb) ` 
+0

好吧,我記得我試圖繼續和它不會中斷,但我會在早上重新檢查。 – Sergi0

+0

當我按下繼續時,沒有任何反應,應用程序繼續運行,並且處理程序中的斷點不會受到影響 – Sergi0

+0

由於我已經演示了所有步驟並顯示我無法再現您的問題,所以除了確保您發送正確的信號給您的流程。 'kill -SIGTERM whatever-the-process-id-is' – jxh