开发者

How do I generate a SIGINT when using XCode to debug?

My console app traps SIGINT so it can exit gracefully.

Pressing CTRL+C inside XCode while the program is being debugged, though, has no effect.

I can find the process and use a terminal window to send a SIGINT to my process, however I'm hoping there's a simpler solution that I can do within XCode开发者_如何转开发.


The pause button of the debugger console actually sends a SIGINT to your app. If you want to make the debugger pass the signal to your app you can do the following:

  1. Press the pause button of the debugger and wait for the debug console to gain focus
  2. Type handle SIGINT pass and press ENTER
  3. Press the Continue button

Now pressing again the Pause button of the debugger console of Xcode will make the SIGINT hit your app.

If you don't want the debugger to stop as soon as the SIGINT is caught you might also want to add handle SIGINT nostop to the previous list.


Update for 2017 / Xcode 8: the proper command(s) for informing lldb of your intention for handling interrupts:

process handle SIGINT -s false
process handle SIGINT -p true

In my experience, even with the above commands, the pause feature of the debugger still will interrupt the app and yield control to the debugger's stack pointer, however a pkill -2 appname at the terminal will trigger your interrupt function without any interaction with the debugger, for example:

void on_signal(int sig) {
  is_interrupted = 1;
}

int main(int argc, const char * argv[]) {
  signal(SIGINT, on_signal);
  // ... do stuff
}


In Xcode 5+ (llvm):

  1. Pause the process

  2. At the (llvm) prompt, enter process signal SIGINT

  3. Resume execution


One solution is to use the UNIX kill or killall commands.

If you know the Process ID you can open the Terminal application and type:

kill -SIGINT 415

(where 415 is the PID for this process)

Or, perhaps easier, you can type

killall -SIGINT my_console_app

(where my_console_app is the name of your app, i.e. the name of the binary created — not the bundle if it's in one)

This will send the signal to all instances of the application, as the name killall suggests, so it may not be appropriate. It might be worth checking if there are other processes with the same name running before you do a killall (;


One of the work-arounds to the hassel of working with interrupts is making a MainMenu with a CTRL-C short-cut that executes your requested routine, or sends itself a SIGINT, if you really need the sig.


Update for XCode 12+

In the modern versions of XCode it is hard to intercept SIGINT. For debug purposes it is better to use SIGINFO in place of SIGINT. You can generate that in Terminal using ^T (CTRL+T).

So during debugging temporary replace SIGINT with SIGINFO in your code. To intercept SIGINFO try next steps all together:

  1. Go to Product > Scheme > Edit Scheme > Run > Options and change Console from Use Xcode to Use Terminal.
  2. Run your program
  3. Pause the program
  4. In the Xcode console, enter this:
(lldb) process handle -p true -s false -n false SIGINFO

You will get:

NAME         PASS   STOP   NOTIFY
===========  =====  =====  ======
SIGINFO      true   false  false
  1. Resume the program
  2. Switch to Terminal and press CTRL+T.

Your signal handler will fire.

Don't forget to return SIGINT back after finishing debugging!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜