Add a new flag '-p', which sets up the parent death signal to `SIGKILL`.
This will cause the kernel to send us a `SIGKILL` as soon as the direct
parent process dies. This is useful e.g. in combination with unshare(1)
from util-linux when using PID namespaces. When unshare forks the child,
which is about to become PID 1, killing the unshare parent will not
cause the child to exit. When executing the command
$ unshare --pid --fork tini -- <prog>
then killing unshare will not cause tini to be killed. Since util-linux
v2.32, unshare has an option "--kill-child=<SIGNAL>" that will set up
the parent death signal for the forked process. This does not help
though in case either SELinux or AppArmor are in use and credentials of
the forked process change (e.g. by changing its UID), as these LSMs will
clear the parent death signal again. The following example would trigger
that situation:
$ unshare --pid --fork setpriv --reuid user tini -s -- <prog>
The parent death signal will get reset by the LSMs as soon as `setpriv`
switchets its user ID to that of "user", and killing unshare will again
not result in tini being killed. The new '-p' flag helps that exact
scenario:
$ unshare --pid --fork setpriv --reuid user tini -s -p SIGKILL -- <prog>
As soon as unshare is getting killed, tini will get signalled SIGKILL
and exit as well, tearing down <prog> with it.
Well designed software should not produce any zombie or re-parenting
processes.
This adds an option to warn in the logs when reaping of zombies is
happening so that it can be monitored and fixed in subsequent releases
of the software.
PR_SET_CHILD_SUBREAPER actually requires a non-zero argument to `prctl`
in order to work..!
Now, this used to work just fine (and currently works in most places)
because when we use a libc that doesn't know about
PR_SET_CHILD_SUBREAPER, it doesn't do anything about the second argument
passed to `pctrl`, so we end up sending some junk in as the second
argument. What we send appears to be completely random and as such seems
very unlikely to be zero, and so things appear to work (e.g. the tests
all pass, etc.).
However, using a libc that does know about this argument (e.g. Ubuntu
Xenial), things *don't* work because the second argument is
automatically set to 0 when we don't provide one.
This probably went unnoticed for a while considering that `tini-static`
isn't affected (it's built on Trusty), and that this mode isn't enabled
by default in the first place.
Also adding a test in run_build.sh to ensure that the pre-processed
license is always up to date with the actual license file.
To recreate: `xxd -i LICENSE > src/license.h`
This changes the execve exit status for the child process to be inline
with standard exit status codes for common execve failures.
I don't think this breaks any backwards compat with existing tini users
because it is still returning a non zero exit status but with correct
codes providing more information why it failed.
- Don't mention options that don't exist in Usage.
- Don't include a log prefix when NO_ARGS is set.
- Turn up the default verbosity to FATAL when NO_ARGS is set.
- Expose verbosity via an ENV var for debugging.
This adds 1k of weight to the resulting binary, which is reasonable
(it's less than 5% for the smaller non-static binary), but alleviates
legitimate user concern that the license requires being included when
Tini is redistributed.
Since we're ignoring SIGTTOU (for good reason), our log messages
could show in another program's output. To make the life of users
easier, let's clarify that the messages are owned by Tini.
In the rare scenario where Tini is not running as PID 1 and its
child (or something else) sets TOSTOP on the tty, then Tini would
hang when if it tries to write debug messages. This commit fixes
this problem by ignoring SIGTTOU.
In the also rare scenario where two Tini instances are running, the
tty-passing could end up being done improperly (if the parent Tini
instance passes the tty to the child before the grandparent Tini
instance passes it to the parent Tini instance), and result in the
parent Tini instance running in the foreground. This commit fixes
this problem by passing the tty in the child (which we can do
because we are ignoring SIGTTOU).
tini only kills the immediate child process. This means that if you
do, for example,
docker run krallin/ubuntu-tini sh -c 'sleep 10'
and ctrl-C it, nothing happens: SIGINT is sent to the 'sh' process,
but that shell won't react to it while it is waiting for the 'sleep'
to finish.
This change adds a -g option to put the child process of tini into a
new process group, and sends signals to that group, so that every
process in the group gets a signal. This corresponds more closely to
what happens when you do ctrl-C etc. in a terminal: The signal is sent
to the foreground process group.
So if you try the example above with a container image that passes -g
to tini, the SIGINT will be received by the 'sleep', and the container
promptly exits.