Make an app impossible to quit - macos

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

Related

How to end an infinite sudo loop with keyboard and not entering the correct password?

Try this in a bash:
while true; do sudo ls; done
If not enter the correct password, this loop can not be stopped by Ctrl+C, Ctrl+\ and Ctrl+D.
Edit: This should not happen in a carefully-written realworld script. I am just curious that if there is a way to escape the loop just with some keyboard shortcuts.
In order to use keyboard shortcut other than Ctrl+C, Ctrl+\ and Ctrl+D.
just use ctrl-z tp pause the process to send it to background and then kill it.
in your command while true; do sudo ls; done
i paused it using ctrl-z and then tried to brought it in foreground using fg.It exits even without killing because when i brought it to foreground only sudo ls was executed..

Bash script that will survive disconnection, but not user break

I want to write a bash script that will continue to run if the user is disconnected, but can be aborted if the user presses Ctrl+C.
I can solve the first part of it like this:
#!/bin/bash
cmd='
#commands here, avoiding single quotes...
'
nohup bash -c "$cmd" &
tail -f nohup.out
But pressing Ctrl+C obviously just kills the tail process, not the main body. Can I have both? Maybe using Screen?
I want to write a bash script that will continue to run if the user is disconnected, but can be aborted if the user presses Ctrl+C.
I think this is exactly the answer on the question you formulated, this one without screen:
#!/bin/bash
cmd=`cat <<EOF
# commands here
EOF
`
nohup bash -c "$cmd" &
# store the process id of the nohup process in a variable
CHPID=$!
# whenever ctrl-c is pressed, kill the nohup process before exiting
trap "kill -9 $CHPID" INT
tail -f nohup.out
Note however that nohup is not reliable. When the invoking user logs out, chances are that nohup also quits immediately. In that case disown works better.
bash -c "$cmd" &
CHPID=$!
disown
This is probably the simplest form using screen:
screen -S SOMENAME script.sh
Then, if you get disconnected, on reconnection simply run:
screen -r SOMENAME
Ctrl+C should continue to work as expected
Fact 1: When a terminal (xterm for example) gets closed, the shell is supposed to send a SIGHUP ("hangup") to any processes running in it. This harkens back to the days of analog modems, when a program needed to clean up after itself if mom happened to pick up the phone while you were online. The signal could be trapped, so that a special function could do the cleanup (close files, remove temporary junk, etc). The concept of "losing your connection" still exists even though we use sockets and SSH tunnels instead of analog modems. (Concepts don't change; all that changes is the technology we use to implement them.)
Fact 2: The effect of Ctrl-C depends on your terminal settings. Normally, it will send a SIGINT, but you can check by running stty -a in your shell and looking for "intr".
You can use these facts to your advantage, using bash's trap command. For example try running this in a window, then press Ctrl-C and check the contents of /tmp/trapped. Then run it again, close the window, and again check the contents of /tmp/trapped:
#!/bin/bash
trap "echo 'one' > /tmp/trapped" 1
trap "echo 'two' > /tmp/trapped" 2
echo "Waiting..."
sleep 300000
For information on signals, you should be able to man signal (FreeBSD or OSX) or man 7 signal (Linux).
(For bonus points: See how I numbered my facts? Do you understand why?)
So ... to your question. To "survive" disconnection, you want to specify behaviour that will be run when your script traps SIGHUP.
(Bonus question #2: Now do you understand where nohup gets its name?)

shell script process termination issue

/bin/sh -version
GNU sh, version 1.14.7(1)
exitfn () {
# Resore signal handling for SIGINT
echo "exiting with trap" >> /tmp/logfile
rm -f /var/run/lockfile.pid # Growl at user,
exit # then exit script.
}
trap 'exitfn; exit' SIGINT SIGQUIT SIGTERM SIGKILL SIGHUP
The above is my function in shell script.
I want to call it in some special conditions...like
when:
"kill -9" fires on pid of this script
"ctrl + z" press while it is running on -x mode
server reboots while script is executing ..
In short, with any kind of interrupt in script, should do some action
eg. rm -f /var/run/lockfile.pid
but my above function is not working properly; it works only for terminal close or "ctrl + c"
Kindly don't suggest to upgrade "bash / sh" version.
SIGKILL cannot be trapped by the trap command, or by any process. It is a guarenteed kill signal, that by it's definition cannot be trapped. Thus upgrading you sh/bash will not work anyway.
You can't trap kill -9 that's the whole point of it, to destroy processes violently that don't respond to other signals (there's a workaround for this, see below).
The server reboot should first deliver a signal to your script which should be caught with what you have.
As to the CTRL-Z, that also gives you a signal, SIGSTOP from memory, so you may want to add that. Though that wouldn't normally be a reason to shut down your process since it may be then put into the background and restarted (with bg).
As to what do do for those situations where your process dies without a catchable signal (like the -9 case), the program should check for that on startup.
By that, I mean lockfile.pid should store the actual PID of the process that created it (by using echo $$ >/var/run/myprog_lockfile.pid for example) and, if you try to start your program, it should check for the existence of that process.
If the process doesn't exist, or it exists but isn't the right one (based on name usually), your new process should delete the pidfile and carry on as if it was never there. If the old process both exists and is the right one, your new process should log a message and exit.

Bash – How should I idle until I get a signal?

I have a script for launchd to run that starts a server, then tells it to exit gracefully when launchd kills it off (which should be at shutdown). My question: what is the appropriate, idiomatic way to tell the script to idle until it gets the signal? Should I just use a while-true-sleep-1 loop, or is there a better way to do this?
#!/bin/bash
cd "`dirname "$0"`"
trap "./serverctl stop" TERM
./serverctl start
# wait to receive TERM signal.
You can simply use "sleep infinity". If you want to perform more actions on shutdown and don't want to create a function for that, an alternative could be:
#!/bin/bash
sleep infinity & PID=$!
trap "kill $PID" INT TERM
echo starting
# commands to start your services go here
wait
# commands to shutdown your services go here
echo exited
Another alternative to "sleep infinity" (it seems busybox doesn't support it for example) could be "tail -fn0 $0" for example.
A plain wait would be significantly less resource-intensive than a spin lock, even with a sleep in it.
Why would you like to keep your script running? Is there any reason? If you don't do anything later after signal then I do not see a reason for that.
When you get TERM from shutdown then your serverctl and server executable (if there is any) also gets TERM at the same time.
To do this thing by design you have to install your serverctl script as rc script and let init (start and) stop that. Here I described how to set up server process that is not originally designed to work as server.

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:
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!

Resources