I have a daemon that starts in initramfs but is being killed by systemd and I'd like it to not to be. Turns out that systemd has a way to prevent a process from being shutdown if the process mutates its own argv.
Processes (run by the root user) whose first character of the zeroth command line argument is @ are excluded from the killing spree, much the same way as kernel threads are excluded too. Thus, a daemon which wants to take advantage of this logic needs to place the following at the top of its main() function:
...
argv[0][0] = '@';
...
std::env::args and std::env::args_os are immutable as far as I can tell.
Does anyone know of a way to mutate argv as systemd would like?
Be aware that this has will disable a couple of things libstd normally handles for you:
if stdin/stdout/stderr are closed, they aren't reopened as /dev/null by libstd. doesn't matter here as systemd will keep all of them open.
no SIGSEGV handler is registered to detect stack overflows and print a nice message. a stack overflow will SIGSEGV, but does not cause UB on x86_64 at least (and any kther arch where stack probing is enabled).
The SIGPIPE signal is not ignored, so attempting to write to a broken pipe will abort the program rather than return EPIPE.
If it matters you can still do all of these things manually.
Since systemd v255, alternatively the SurviveFinalKillSignal=yes unit option can be set, and provides the equivalent functionality to modifying argv[0][0].
It seems this would be a better option in Rust. Seems v255 is the most recent version as of writing this (released in December 2023) so if you need to support slow moving non-rolling release distros that probably isn't an option currently.
That said it is really weird to me that Rust doesn't have an API to do this in the standard library.
It’s not a direct answer to your question, but does it work to set argv[0] to something different when you run the program instead? For example, in bash you could write exec -a @myprogram /bin/myprogram.