troglobit / finit

Fast init for Linux. Cookies included
https://troglobit.com/projects/finit/
MIT License
622 stars 61 forks source link

[bug?] shtudown and later hook scripts lose access to initctl #320

Closed hongkongkiwi closed 1 year ago

hongkongkiwi commented 1 year ago

This might be expected behaviour, but I found it a little bit unexpected so I thought I would report it.

I have a shutdown hook script (sys/shutdown/myscript) and inside I'm checking if a process is running or not so I can know how to proceed. I'm using initctl -q status <svc_name> and checking error code (for background the process is a serial port multiplexor type program so I will use that if running, or else send direct to serial if not running):

When using initctl here, the it shows:

~ # reboot
[ ⋯  ] Calling /usr/share/finit/hooks/sys/shutdown/50-notify-nordicreboot: Timed out waiting for reply from Finit.
initctl: Timed out waiting for reply from Finit.
~ #

Then it kicks me back to console.

I think firstly.... is it expected behaviour that a hook script can abort shutdown or reboot by failing? If so, I think we should clearly document it because it was a surprise to me. My preference is to log error codes, but to continue shutdown or reboot anyway if one of the hook scripts fails.

And secondly, I would expect some basic functions of initctl to be available here, such as status. the problem resolved itself when I used ps | grep -v | grep -q 'appname' instead of initctl but that feels clunky to me.

Then it kicks me back to console

troglobit commented 1 year ago

Hmm, it should definitely not be able to abort the shutdown/reboot ... there's simply no code for that. I'll have to check myself to see what's going on here.

Re calling initctl in shutdown: I understand the expectation, however:

  1. Hook scripts are very crude "hack" to allow some execution on the outside, they were never really intended to be this advanced, sorry.
  2. Finit is single threaded and all the hooks (regardless if it's a C plugin or script) are run in sequence until they've all completed.
  3. We could of course fork off the scripts and wait for them to return, but that's not how things are designed right now.

So, Finit is blocking while hook scripts run, and the initctl status [foo] operation from your script is an IPC to PID 1 requesting the full status of foo ... so yeah, it will not work. Stick to simple operations that don't need interaction with Finit.

hongkongkiwi commented 1 year ago

So, Finit is blocking while hook scripts run, and the initctl status [foo] operation from your script is an IPC to PID 1 requesting the full status of foo ... so yeah, it will not work. Stick to simple operations that don't need interaction with Finit.

Yes, you confirmed my thinking there.

Curiously though, it works fine during all the startup scripts.... is that expected? e.g. from the first early stage hook script in "banner" I can use initctl -q status <svcname>.

troglobit commented 1 year ago

I guess that's because the IPC socket (/var/run/finit/socket) doesn't even exist yet, iirc there's an exception for that in the client code, I think it returns a non-zero error code. Otoh, when the socket file exists the client code tries to connect and instead times out.

troglobit commented 1 year ago

OK, reproduced ... thanks for reporting this, very nasty!

Edit: I tested an (obvious) idea before leaving for work -- closing the IPC socket when changing to runlevel 0/6. This closes the window for any spurious calls and makes easier for the initctl program to return better status. (I'll update initctl out-of-band of this issue.)