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

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:
Press the pause button of the debugger and wait for the debug console to gain focus
Type handle SIGINT pass and press ENTER
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):
Pause the process
At the (llvm) prompt, enter process signal SIGINT
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:
Go to Product > Scheme > Edit Scheme > Run > Options and change Console from Use Xcode to Use Terminal.
Run your program
Pause the program
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
Resume the program
Switch to Terminal and press CTRL+T.
Your signal handler will fire.
Don't forget to return SIGINT back after finishing debugging!

Related

Why is rust process causing terminal errors on Ctrl+C?

My program has a process::Command spawned and waited. In that process is a bash command running a command that will also wait for an exit signal to stop the process. For example,
let shell = "bash";
Command::new(shell)
.arg("-c")
.arg("watch command") // watch command won't stop until it gets a Ctrl+C
.spawn()
.unwrap();
.wait()
.unwrap();
During the process is running, if I type Ctrl+C I get two questions about whether to terminate the process or not (Y/N) consequently. If I just type Ctrl+C for just a few more times, the process will exit. But when I chose to answer the question with Y or N, the terminal will break. I can't type commands, Enter keys won't work, cannot even exit from the terminal. The new commands I type will replace the current texts on the terminal, and I can even delete the terminal texts like a text editor.
I don't know what was causing the error. Am I doing something wrong? How do I add an event listener that will listen for Ctrl+C command and exit the process completely on the event?

Make an app impossible to quit

I want to make an app I have impossible to quit by normal means, only by forcequitting. Is this possible? (I do have limited knowledge of bash)
I use MacOSX ElCapitan. Thank you in advance for the help!
Edit: To clarify, I want it not to be able to quit with ⌘+Q or by rightclicking the app and pressing quit, or quitting through the App menu on the top bar.
You could intercept any control-c type signals with a signal handler.
Here is an example:
#!/bin/bash
trap "echo 'Caught Signal'" SIGHUP SIGINT SIGTERM
while true; do
echo "looping"
sleep 5
done

Trying to exit Ruby processes

When I attempt to exit ruby processes, namely, specs, rails console, and binding.pry calls, there are two options: ctrl+c, ctrl+z, or if things are really stuck, open a separate tab and killall ruby. However, when I ctrl+c the first time, the terminal outputs Exiting... Interrupt again to exit immediately. but hangs permanently. If I ctrl+c again to force exit, it successfully exits. However, from that point on, I can no longer see what I'm typing into the shell. So if I type ls, the line will still appear blank, but if I hit enter, it will successfully execute the ls command.
When I ctrl+z, it manages to stop the process successfully. However, after doing this a few times, I wind up with a bunch of ruby processes running, which seem to block running new ruby processes. In this scenario, killall ruby does nothing (nor does any derivative such as looking up by pid). I have to open activity monitor (mac) and force quit each proc individually.
Any ideas how I managed to get myself into this/how to resolve it?
Killing all your Ruby instances is a shotgun approach; you might hit targets you didn't intend, so I suggest to avoid it.
When your shell doesn't show what you're typing any more you need to (blindly) enter reset to reset the terminal.
Ctrl+Z doesn't kill your process, it just get's suspended. You should get an output that tells you a job number, like:
[1] + 95295 suspended man reset
Here, 1 is the job number. You can then resume the command by typing fg %<jobnumber>, in this example fg %1. Or you can kill it with kill -9 %<jobnumber>, like kill -9 %1.

Send Ctrl-C to app in LLDB

I have an CLI app that is seg faulting during termination (After sending a Ctrl-C)
Pressing Ctrl-C in lldb naturally pauses execution.
Then I try:
(lldb)process signal SIGINT
(lldb)process continue
But that doesn't actually seem to do anything to terminate the app.
Also tried:
(lldb)process signal 2
The debugger uses ^C for interrupting the target, so it assumes that you don't actually want the ^C propagated to the target. You can change this behavior by using the "process handle" command:
(lldb) process handle SIGINT -p true
telling lldb to "pass" SIGINT to the process.
If you had stopped the process in lldb by issuing a ^C, then when you change the process handle as shown here and continue, that SIGINT will be forwarded to the process.
If you stopped for some other reason, after specifying SIGINT to be passed to the process, you can generate a SIGINT by getting the PID of the debugee using the process status and send a SIGINT directly to said process using platform shell:
(lldb) process status
(lldb) platform shell kill -INT {{PID from previous step}}
(lldb) continue
The easiest way I found was just to send the process a SIGINT directly. Take the pid of the debuggee process (which process status will show you) and run
kill -INT <pid>
from another terminal.

How can I send a Unix signal to an app running under debug mode within Xcode?

I'm making a command-line app. I want to test Ctrl+C or SIGUSR1, but I couldn't find any way to send some signal to them.
I tried kill -s INT <pid>. I got <pid> with ps -A | grep $PROGAM_NAME But this causes debugger popup, and doesn't call my signal handler. Of course I installed custom signal handler with signal() function.
Why this doesn't work? And How can I send some signal to the process under debugging?
get the pid from the application, write it to a file (so you can find it) and then run the kill

Resources