I'm supervising an instance of an X Server using s6.
X.Org has a built-in readiness notification mechanism: it sends a USR1
to its parent process once it's ready. From what I know, it would be
This... 😱 this is appalling.
This mechanism is a terrible way to notify readiness.
1. It forces the program reading readiness information to be the
direct parent of the daemon.
2. This is not a concern for X, but if the daemon has dropped
privileges, it is very possible that it does not have the rights to
signal its parent anymore.
3. It forces the parent to use the siginfo_t structure, and more
complex signal management, in order to detect what process is sending
the signal. This can work, but is by no means a common use of signals.
4. Signals can be lost if several signals of the same value are
received by a process. So if two processes are notifying readiness at
the same time to a unique supervisor via SIGUSR1, it is possible that
the supervisor only gets one of them.
However, after reading the documentation, there doesn't seem to be a
way to set up custom USR1 handlers for s6-supervise.
Indeed, there isn't. Signals are meant to be a control mechanism from
above, not from below: the administrator is supposed to be able to send
signals to s6-supervise, but the supervised process *definitely is not*.
As far as I know,
this leaves me with two, not quite ideal solutions: make the run
script spawn X and do readiness notification on its behalf (which
lengthens the supervision chain), or poll it (which is what I've been
doing). Is there a way to not let the information from this USR1 not
"go to waste"?
Let this "information" go to waste: it should never be sent in the
first place, and if patching were to happen, it should be to delete
that chunk of code from the Xorg server. We should consider ourselves
lucky that s6-supervise is not using SIGUSR1 for its own purposes and
is happily ignoring it as is.
Fortunately, there is a different solution for you: the -displayfd
to the X command will print the display number, followed by a newline,
to the (argument of -displayfd) file descriptor, when X has found a
display. This only happens when X is ready - unless it only starts
listening to its socket later, but the window should be super small; and
it has the correct format for an s6 notification.
So, using displayfd as your notification fd will work.
For instance, if you have 3 in your notification-fd file, starting
X -displayfd 3 should properly (or *almost* properly) notify readiness.
Some people already use that mechanism, and are happy with it. :)