Laurent Bercot wrote:
That is true, I hadn't thought of abstract sockets, and it would work.
However, changing the way poweroff signals init is a big change, and
in particular, making init listen to a socket is very significant: you
know need to multiplex reaping zombies with listening to connections.
It's not hard, but it requires patching init significantly, reworking
its control flow around an asynchronous event loop; and at that point
you're just better off using a better pid 1 process (such as s6-svscan,
which already does this - have you considered switching inits? ;)). And
changes of that magnitude are pretty dangerous - I'm quite convinced
there are some people relying on the "send a signal to init" mechanism
and whose systems would break if that mechanism were changed.
The "send a signal to init" mechanism is a good one, and does not
fundamentally need to be changed; your problem is a readiness detection
one, i.e. whatever mechanism you're using to tell init to shutdown, you
can't use it before init is ready to handle it.
And that's where abstract sockets can be useful: you can use abstract
sockets as a simple synchronization mechanism. The easiest way to do it
would be: when init has installed its signal handlers, it creates an
abstract socket (close-on-exec, of course) and binds it - but does not
listen to it and does nothing else with it). And poweroff checks for
the presence of this socket by repeatedly attempting connect(). When
errno changes from ENOENT to ECONNREFUSED, it means the socket has been
created and init is now ready to receive signals.
This requires minimal change to init and a small polling addition
to poweroff - which I think is much better and safer than a heavy change
to busybox's init.
I think your idea with wait is better. It doesn't require any additional
code to the init process, it is likely more portable, it doesn't consume
memory for an open socket and the changes to poweroff are also smaller.
I would modify it so that it doesn't check for the presence of the
grandchild, as the grandchild may be started from a process that does
not do wait. Just check whether the parent PID is 1 or not.
Basically:
if ((pid1 = fork ()) > 0) exit (0);
if ((pid2 = fork ()) > 0) exit (0);
while (pid1 > 0 && pid2 > 0 && getppid () != 1) // only wait if both
fork calls were successful
sleep (1);
If fork fails, it should signal init from the parent process. If there
are not enough resources to create a new process, we can safely assume
that init is ready to receive a signal.
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox