How to detect restart before terminating program on Linux - linux

I want to detect that system is restarting before it terminates my program on Linux.
I tried using /var/run/utmp file to detect runlevel, put inotify on its changes but seems like system is closing this program before I get signal. I catch shutdown with it if I set runlevel with telinit command, but dont catch if I just restart with button on top-right corner in Ubuntu.
Any idea how can it be done?

Catch the SIGTERM signal and be quick with saving/doing whatever and then exit. You've got approximately 10 seconds before you'll get SIGKILL which you can't catch, and you'll be force terminated.
If the system isn't sending you a SIGTERM to allow proper shutdown, change your system to something proper, this is the standard way of doing it.
See man 7 signal and man 3 sigaction for signal handling.
(Note that I don't know of a standard way to check if a system is rebooting or not, I don't think such thing exists. But as mentioned above, a proper system will send you SIGTERM and let you do your cleanup/exit. Hard reboot excluded, because thats almost equivalent of pulling the power cord.)

Related

Programing Rust to stop safety with systemctl

I'm writing a very demanding program in rust that had variable Threads for processing very important data, and want to know if there is a way that i can send a signal to stop it with systemctl in a way that i can be sure that it is finishing it's dutties before stop, as its very demanding, uses http_request, and threads are variables I can not make an estimation of how much time i have to wait since signal sended until the process is dead.
In esscense, it is a daemon that is in a loop until a variable sets false, like this
loop {
// Process goes here
if !is_alive {
break;
}
}
What i'm doing right now is that the program is asking a "config.json" file if it is "alive", but i think it's not the best way because i don't know when the program stops, just can see that is stoping, but not how much is going to last, and if i do this way, systemctl is going to show the service alive, even if i shuted it down manually.
If you want to experiment with Systemd service behavior, I would take a look at the Systemd documentation. In this case, I would direct you to the section about TimeoutStopSec.
According to the documentation, you can disable any timeout on systemd stop commands with TimeoutStopSec=infinity. This combined with actually handling the SIGTERM signal that systemd uses by default should do the trick.
Furthermore, there is the KillSignal option by which you can specify the signal that is sent to your program to stop it or ExecStop to specify a program to run in order to stop your service.
With these you should be able to figure it out, I hope.

Signal generated for closing the window?

I'm using centOs 6.3(Final) version. My question is which signal is generated on pressing the close button for a window? Is the close button equivalent to alt-f4? Or is my whole understanding is wrong and centOs does not use the signal model for it's graphical windows?
If possible please specify the source of the answer since I need to document it.
Thanks
Assuming we are talking about at the X11 level here then the signal you are looking for is likely WM_DELETE_WINDOW or the DestroyRequest/DestroyNotify event.
This has nothing to do (again at the X11 level) with signal(2) or signal(7). Though it is entirely possible that in some circumstances (hung processes or similar) that those signals would be used to terminate the terminal process.
It is also likely that the shell/etc. running inside the terminal are going to receive various signals which terminate their operation.
As said here: You can use wmctrl:
wmctrl -c appName
More aggressive would be to grep the PID to send a POSIX signal like SIGTERM (15, Ctrl-c) (see notes below).
Notes
Very similar to How can I kill a specific X window
You can also try with xdottool

What is the proper way to shutdown linux and then kill power?

I am running Linux raspberrypi 3.6.11+ on a raspberrypi board with an external power supply. The power supply "off" switch is controlled via the GPIO's.
I'd like to do a "shutdown -h -P now", wait for the system to shutdown (halt), then kill the power by running a program (killpower) to toggle the appropriate gpio pin. My main goal is to ensure that the file system is in a state where it won't get corrupted when the power is removed.
I've tried to take advantage of the runlevel 1 script killproc that sends SIGTERM (and SIGKILL) to every running process. I wrote killpower to catch SIGTERM, wait 20 seconds, then send the gpio powerkill sequence. I also modified the killproc script to NOT SIGKILL my killpower pid even if it is still running after the SIGTERM timeout.
When this did not work, I discovered that after killproc runs, the /init.d/halt SCRIPT runs, which calls /sbin/halt. /sbin/halt also kills all processes with SIGKILL, so I expect my killpower proc got killed before the 20 seconds was up. Now, I don't see how this approach is going to work.
I also see that init can act on a SIGPWR signal (not recommended) but it can execute powerwait/powerfail. Is the system in a state to power off at this point? I can't seem to find out what these programs are supposed to implement.
I thought about installing another shutdown script in init.d but I'm confused about what run level it should "stop" at (level 1 or level 0).
Is it OK to kill power just before the /sbin/halt is executed as a result of the shutdown command? Am I correct that once /sbin/halt is executed, nothing else will ever run?
The way I power off a linux box when I am logged into it remotely is to simply use the 'poweroff' command. The system then shuts down properly and finally turns itself off--nothing more, nothing less, exactly what I want.

Linux process in background - "Stopped" in jobs?

I'm currently running a process with the & sign.
$ example &
However, (please note i'm a newbie to Linux) I realised that pretty much a second after such command I'm getting a note that my process received a stopped signal. If I do
$ jobs
I'll get the list with my example process with a little note "Stopped". Is it really stopped and not working at all in the background? How does it exactly work? I'm getting mixed info from the Internet.
In Linux and other Unix systems, a job that is running in the background, but still has its stdin (or std::cin) associated with its controlling terminal (a.k.a. the window it was run in) will be sent a SIGTTIN signal, which by default causes the program to be completely stopped, pending the user bringing it to the foreground (fg %job or similar) to allow input to actually be given to the program. To avoid the program being paused in this way, you can either:
Make sure the programs stdin channel is no longer associated with the terminal, by either redirecting it to a file with appropriate contents for the program to input, or to /dev/null if it really doesn't need input - e.g. myprogram < /dev/null &.
Exit the terminal after starting the program, which will cause the association with the program's stdin to go away. But this will cause a SIGHUP to be delivered to the program (meaning the input/output channel experienced a "hangup") - this normally causes a program to be terminated, but this can be avoided by using nohup - e.g. nohup myprogram &.
If you are at all interested in capturing the output of the program, this is probably the best option, as it prevents both of the above signals (as well as a couple others), and saves the output for you to look at to determine if there are any issues with the programs execution:
nohup myprogram < /dev/null > ${HOME}/myprogram.log 2>&1 &
Yes it really is stopped and no longer working in the background. To bring it back to life type fg job_number
From what I can gather.
Background jobs are blocked from reading the user's terminal. When one tries to do so it will be suspended until the user brings it to the foreground and provides some input. "reading from the user's terminal" can mean either directly trying to read from the terminal or changing terminal settings.
Normally that is what you want, but sometimes programs read from the terminal and/or change terminal settings not because they need user input to continue but because they want to check if the user is trying to provide input.
http://curiousthing.org/sigttin-sigttou-deep-dive-linux has the gory technical details.
Just enter fg which will resolve the error when you then try to exit.

Linux i/o to running daemon / process

Is it possible to i/o to a running process?
I have multiple game servers running like this:
cd /path/to/game/server/binary
./binary arg1 arg2 ... argn &
Is it possible to write a message to a server if i know the process id?
Something like this would be handy:
echo "quit" > process1234
Where process1234 is the process (with sid 1234).
The game server is not a binary written by me, but it is a Call of Duty binary. So i can't change anything to the code.
Yes, you can start up the process with a pipe as its stdin and then write to the pipe. You can used a named or anonymous pipe.
Normally a parent process would be needed to do this, which would create an anonmyous pipe and supply that to the child process as its stdin - popen() does this, many libraries also implement it (see Perl's IPC::Open2 for example)
Another way would be to run it under a pseudo tty, which is what "screen" does. Screen itself may also have a mechanism for doing this.
Only if the process is listening for some message somewhere. For instance, your game server can be waiting for input on a file, over a network connection, or from standard input.
If your process is not actively listening for something, the only things you can really do is halt or kill it.
Now if your process is waiting on standard input, and you ran it like so:
$ myprocess &
Then (in linux) you should be able to try the following:
$ jobs
[1]+ Running myprocess &
$ fg 1
And at this point you are typing standard input into your process.
You can only do that if the process is explicitly designed for that.
But since you example is requesting the process quit, I'd recommend trying signals. First try to send the TERM (i.e. terminate) signal which is the default:
kill _pid_
If that doesn't work, you can try other signals such as QUIT:
kill -QUIT _pid_
If all else fails, you can use the KILL signal. This is guaranteed (*) to stop the process but the process will have no change to clean up:
kill -KILL _pid_
* - in the past, kill -KILL would not work if the process was hung when on a flaky network file server. Don't know if they ever fixed this.
I'm pretty sure this would work, since the server has a console on stdin:
echo "quit" > /proc/<server pid>/fd/0
You mention in a comment below that your process does not appear to read from the console on fd 0. But it must on some fd. ls -l /proc/<server pid/>/fd/ and look for one that's pointing at /dev/pts/ if the process is running in a gnome-terminal or xterm or something.
If you want to do a few simple operations on your server, use signals as mentioned elsewhere. Set up signal handlers in the server and have each signal perform a different action e.g.:
SIGINT: Reread config file
SIGHUP: quit
...
Highly hackish, don't do this if you have a saner alternative, but you can redirect a process's file descriptors on the fly if you have ptrace permissions.
$ echo quit > /tmp/quitfile
$ gdb binary 1234
(gdb) call dup2(open("/tmp/quitfile", 0), 0)
(gdb) continue
open("/tmp/quitfile", O_RDONLY) returns a file descriptor to /tmp/quitfile. dup2(..., STDIN_FILENO) replaces the existing standard input by the new file descriptor.
We inject this code into the application using gdb (but with numeric constants, as #define constants may not be available), and taadaah.
Simply run it under screen and don't background it. Then you can either connect to it with screen interactively and tell it to quit, or (with a bit of expect hackery) write a script that will connect to screen, send the quit message, and disconnect.

Resources