killall checks once per second if any of the killed processes still exist ...
That'll get the job done, but I find it odd that they'd implement this through periodic checks rather than a wait()/waitpid().
]]>ExecStop=/usr/bin/killall --user kodi --exact --wait kodi-x11
*note: this is almost certainly the real problem: pkill sends the signal to kodi-x11 and then pkill itself exits immediately effectively saying "I'm done, I sent my signal" - but pkill does not wait for kodi-x11 to finish handling that signal. If there were a version of pkill that sent the signal then called a waitpid() on the pid it sent it too, the problem would most likely be solved.
]]>If I start the kodi-x11.service and then as root:
# timeout 8 /usr/bin/pkill --newest kodi-x11
I get the desired result as seen by running `tail -f /var/lib/kodi/.kodi/temp/kodi.log` in another shell. There, you see kodi do all its housekeeping tasks upon receiving the SIGTERM and then that PID disappears:
...
2020-10-24 10:00:56.243 T:139740558294848 NOTICE: Quitting due to POSIX signal
2020-10-24 10:00:56.283 T:139740558294848 NOTICE: Stopping player
2020-10-24 10:00:56.283 T:139740558294848 NOTICE: Storing total System Uptime
2020-10-24 10:00:56.283 T:139740558294848 NOTICE: Saving settings
2020-10-24 10:00:56.285 T:139740558294848 NOTICE: Saving skin settings
2020-10-24 10:00:56.285 T:139740558294848 NOTICE: Stopping all
2020-10-24 10:00:56.285 T:139740558294848 NOTICE: ES: Stopping event server
2020-10-24 10:00:56.285 T:139740558294848 NOTICE: CWebServer[8080]: Stopped
2020-10-24 10:00:57.280 T:139739092997696 NOTICE: ES: UDP Event server stopped
2020-10-24 10:00:57.889 T:139740558294848 NOTICE: Application stopped
2020-10-24 10:00:58.089 T:139740558294848 NOTICE: XBApplicationEx: destroying...
2020-10-24 10:00:58.100 T:139740558294848 NOTICE: unload skin
2020-10-24 10:00:58.116 T:139740558294848 NOTICE: unload sections
2020-10-24 10:00:58.170 T:139740558294848 NOTICE: XBApplicationEx: application stopped!
By contrast, when I use the same command as the ExecStop line, systemd does not seem to wait for the PID to go away on its own at all. If I tail the same log file, none of the house keeping tasks are allowed to run. What am I missing?
ExecStop=/usr/bin/timeout 8 /usr/bin/pkill --newest kodi-x11
A single ExecStop a hard-coded sleep high number can cover this but that could lead to a race condition if kodi is still busy:
ExecStop=/usr/bin/pkill --newest kodi-x11 ; /usr/bin/sleep 15s
What is the the correct way to write the service so that systemd will wait for a specific PID to exit on its own (defined by pgrep --newest kodi-x11)?
]]>My understanding from a kodi developer is there is a slow 500 ms loop that listens for the SIGTERM.
Signals are interrupts. The handler is called instantly regardless of the polling rate of any other processing of the code, and any sane loop would retest the loop condition after continuing from a signal (this is the case for all code I've ever seen that runs an event loop - e.g., using select, etc). So the 500ms shouldn't really be relevant - only the time actually needed to write to the file should be relevant. But I guess if the sleep works, go with it.
]]>There are 2 goals:
1) Insure that the data on shutdown get written out.
2) Exit with a return code that reflects reality.
Note that kodi-x11 with xinit is just 1 of 3 use cases/services. There are also separate services for kodi-gbm (more simplistic without the ExecStop= at all) and kodi-wayland. See them here: https://github.com/graysky2/kodi-standa … 1b422/init
]]>I think this one is solved unless folks think my implementation is too hacky and have a more technically correct suggestion.
]]>@progandy - I am not entirely sure. Kodi should write out its cumulative uptime to ~/.kodi/userdata/guisettings.xml on a successful exit. With the service as-is, this is not happening. I do not know if it is because systemd kills it faster than the write out, or because killing xinit ends in a different state for kodi, or both.
Systemd has different kill modes (see manpage systemd.kill) The default is "control group" which will send SIGTERM to all subprocesses of the service. Then after a timeout (default 90s I think) it will send SIGKILL to all of them. If you choose "mixed", then only $MAINPID will get SIGTERM, systemd expects that to stop all other processes. After the timeout all processes still get SIGKILL if they haven't stopped.
I suggested changing to the "mixed" mode and testing it.
I am happy to test out some configurations for pkill which I will do when I have some time to explore. If you have a favorite suggestion, please let me know (perhaps --newest)?
EDIT: Sending `/usr/bin/pkill --newest kodi-x11` from the CLI while the service is running gives the intended effect. I will code it into the formal service when I have some time and test it. Thanks for the suggestion :thumbs up:
]]>