2

I have console C++ application built in XCode 6 and want to add SIGTERM handler to it. There are a lot of examples, but I can't get them to work.

#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;
}

The debugger stopped on the while statement, but the handler was not called. The same problem with this code

#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;
}

Is there a problem with the code? What is the right way to handle signals in OSX?

jxh
  • 69,070
  • 8
  • 110
  • 193
Sergi0
  • 1,084
  • 14
  • 28
  • 1
    How are you delivering the signal? – jxh May 28 '15 at 20:12
  • @jxh by using "kill". the problem is that XCode breaks execution of the cycle and actually shows message that execution was interrupted by SIGTERM. but the handler doesn't get called. – Sergi0 May 28 '15 at 20:26
  • Can you put the break point on the `return` instead of the `while`? I am not sure what breaking on the `while` buys you. – jxh May 28 '15 at 20:29
  • @jxh I didn't put any breakpoints there, XCode does that automatically. the only breakpoint placed me is inside the handler – Sergi0 May 28 '15 at 21:12

3 Answers3

2

After you send the signal, and the debugger stops, you have to continue to get to your breakpoint inside the signal handler.

(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) `
jxh
  • 69,070
  • 8
  • 110
  • 193
  • well, I recall I tried to continue and it wouldn't break, but I'll recheck in the morning. – Sergi0 May 28 '15 at 21:58
  • nothing happens when I press continue, the app continue to run, and the breakpoint inside handler doesn't get hit – Sergi0 May 29 '15 at 01:32
  • Seeing as I have demonstrated all my steps and shown I cannot reproduce your problem, I cannot help you any further, other than to make sure you are sending the correct signal to your process. `kill -SIGTERM whatever-the-process-id-is` – jxh May 29 '15 at 02:28
  • well, i'm sure that SIGTERM signal is send, cause I tried both kill versions and XCode actually tells me that execution was broke by SIGTERM. I'm yet to check donjuedo link about lldb – Sergi0 May 29 '15 at 08:57
1

Your code is fine. Kill with:

kill -SIGTERM 31573

because

kill -9 31573

where 31573 was my process ID, did not exit gracefully. I added a printf to your code to tell me it was exiting gracefully.

donjuedo
  • 2,475
  • 18
  • 28
  • Oops. I did that work on Ubuntu, not the OS X I just noticed. Now I'm crossing my fingers that the answer works for you, too. – donjuedo May 28 '15 at 20:44
  • `kill -9` is not at all equivalent to `kill -SIGTERM`, which is why your process did not exit gracefully with `kill -9`. `SIGKILL`, a.k.a. signal number 9, is not trappable. `SIGTERM` is generally signal 15 on Linux - not sure if OSX orders their signals differently or not... – twalberg May 28 '15 at 20:55
  • OK, I'm home now and working on my Mac. Again, your code (second sample specifically) has proven just fine. The confirmation was done in Terminal with gcc and "kill -TERM ". Source refers to SIGTERM, like normal, but kill refers (on OS X) to TERM. The XCode pause you are seeing is due to XCode, not your code. I tried it both ways, Terminal and XCode. I could not find a pref to inhibit that interruption, however. – donjuedo May 29 '15 at 00:46
  • nothing new happens. i get a break on the while operator saying "Thread 1: signal SIGTERM", when I press continue the cycle never breaks and breakpoint in the handler is never hit – Sergi0 May 29 '15 at 01:34
  • Just to focus here ...You asked, Is there a problem with the code? Answer: No. You asked, What is the right way to handle signals in OSX? Answer: The way you're already doing it. New question: How do I get XCode (lldb) to not pause when signals occur? Answer: http://stackoverflow.com/questions/11984051/how-to-tell-lldb-debugger-not-to-handle-sigbus – donjuedo May 29 '15 at 03:33
  • @donjuedo please post that as an answer – Sergi0 May 29 '15 at 12:28
1

OK, I'm home now and working on my Mac. Again, your code (second sample specifically) has proven just fine. The confirmation was done in Terminal with gcc and "kill -TERM ". Source refers to SIGTERM, like normal, but kill refers (on OS X) to TERM. The XCode pause you are seeing is due to XCode, not your code. I tried it both ways, Terminal and XCode. I could not find a pref to inhibit that interruption, however.

Just to focus here ...You asked, Is there a problem with the code? Answer: No. You asked, What is the right way to handle signals in OSX? Answer: The way you're already doing it. New question: How do I get XCode (lldb) to not pause when signals occur? Answer: How to tell LLDB debugger not to handle SIGBUS?

Community
  • 1
  • 1
donjuedo
  • 2,475
  • 18
  • 28
  • (un?)fortunately, you are right, when in debugger session the handler won't work, cause debugger intercepts the signals. – Sergi0 May 29 '15 at 14:27
  • 1
    I think you can still do this. When I looked at "man lldb", I saw mention of 3 files that are read by lldb when launched. I have used .gdbinit files with gdb to set up breakpoints, etc., saving me manual set up with each and every debug session. So I'd bet if you tailor the stackoverflow answer referenced above to your SIGTERM, you could put that command in the init file for lldb, and XCode will invoke lldb and behave as you wish. I think. – donjuedo May 29 '15 at 15:25