Almost all programs are simple and have only a single command. When
printing options, let's just use the first COMMAND block found by default.
This means we can drop the explicit program-name argument and reduce
copy&paste boilerplate.
Previously, when a library was dynamically loaded via a helper function
inside libsystemd-shared.so, the resulting dlopen ELF note was not
propagated to the invoking executable's ELF metadata.
This commit explicitly annotates each executable with the relevant
dlopen ELF notes for any optional dependencies it might potentially
load. This ensures that package managers and build systems can properly
discover runtime dependencies that are triggered indirectly.
Our baseline glibc is 2.34, which merged libdl, libpthread (the
dependency('threads') target), and librt into libc. Empty .so/.a stubs
remain for backward compatibility with old binaries, but new builds
resolve dl_*, pthread_*, mq_*, timer_*, etc. directly from libc.
On musl the same libraries are likewise empty stubs.
Drop the libdl, threads, and librt entries from every meson.build, and
remove the now-stale 'Libs.private: -lrt -pthread' from libudev.pc.in
since both flags resolve to empty link-time stubs on glibc 2.34+ and
musl.
Verified with readelf -d that libsystemd.so, libudev.so, and systemd no
longer carry DT_NEEDED entries for libdl/libpthread/librt.
I am really not a fan of full code lines passed to macros as parameters.
Let's get rid of the 3rd parameter of FOREACH_OPTION() hence:
1. Let's return errors just as a regular value (though a negative one),
that can be handled via a OPTION_ERROR case statement for the switch.
This normalizes handling of the error, just like any other event
returned by the option parser.
2. In order to avoid exploding the amount of boilerplate in each use
(that just propagates the error on OPTION_ERROR), let's then
introduce an explicit FOREACH_OPTION_OR_RETURN(), that returns from
the calling function on its own (and makes that clear in the name).
Together this cleans up, normalizes the logic and shortens the code.
It was requested to make the 'c', 'opt', and 'arg' params the same, i.e.
defined through the FOREACH_OPTION macro. But we can't do that easily,
because 'c' was defined in the for loop definition, and we can only
define variables of the same type in that way. Also, in some cases we
need only 'c', in other cases with need 'c' and 'arg, in some cases 'c'
and 'opt', and in other cases all three. We'd need to either
conditionalize or mark those variables with _unused_ to deal with
compiler warnings. But a different approach works quite nicely: add
state.opt and state.arg to show the current option and it's argument.
(The short names are picked on purpose to reduce verbosity since those
are used a lot.)
Although extremely unlikely, there is a race present in solely checking the
$LISTEN_PID environment variable, due to PID recycling. Fix that by introducing
$LISTEN_PIDFDID, which contains the 64-bit ID of a pidfd for the child process
that is not subject to recycling.
Even if we're not using --accept=, it's very useful to be able to
synchronize on systemd-socket-activate having binded to its listen
socket, so let's always send READY=1. This means the payload can't
send READY=1 anymore but it's doubtful whether that's useful in this
case in the first place.
Add a --now option that starts the program instantly, instead of waiting for a
connection on the socket. This is useful, for instance, when developing:
Say I have a Rust, socket-activated web service. I can test it with:
systemd-socket-activate -l 8080 --fdname=http cargo run
However this delays running the service (which potentially involves compilation)
to when I try to connect to it, which wastes time. Since it delays compilation,
I also don't see any warning or errors in the code until it gets a connection
either.
The name's now a bit of a misnomer, since starting the service immediately isn't
really socket activation, but oh well ¯\_(ツ)_/⁻
Check user configuration errors and warnings (e.g. more than one socket passed
with --inetd) earlier in runtime. There's no reason not to do this, and it means
invalid configuration will be reported to the user earlier.
Also let the user know that --fdname= has no effect with --inetd.
This commit cleans up the includes for all the small tools across
the tree.
A few cases of returning EXIT_SUCCESS are replaced with returning
0 to avoid including <stdlib.h>.
Split out of #37344.
Currently, NOTIFY_READY from daemon-util.h conflicts with NOTIFY_READY
from NotifyState from service.h so let's rename the constants to avoid
the conflict.
When we pass information about our calling terminal on to some service
or command we invoke, propagate $COLORTERM + $NO_COLOR in addition to
$TERM, in order to always consider the triplet of the three env vars the
real deal.
Sometimes it makes sense to hard kill a client if we die. Let's hence
add a third FORK_DEATHSIG flag for this purpose: FORK_DEATHSIG_SIGKILL.
To make things less confusing this also renames FORK_DEATHSIG to
FORK_DEATHSIG_SIGTERM to make clear it sends SIGTERM. We already had
FORK_DEATHSIG_SIGINT, hence this makes things nicely symmetric.
A bunch of users are switched over for FORK_DEATHSIG_SIGKILL where we
know it's safe to abort things abruptly. This should make some kernel
cases more robust, since we cannot get confused by signal masks or such.
While we are at it, also fix a bunch of bugs where we didn't take
FORK_DEATHSIG_SIGINT into account in safe_fork()
When we call safe_fork() with the first argument set (process name), we
call rename_process() that zeroes out saved argv (that was saved by
save_argc_argv() in the main func defined by DEFINE_MAIN_FUNC()). In this
case this means that with --accept both the target executable name and
its arguments will be empty strings:
```
$ systemd-socket-activate --accept --listen 1111 cat &
Listening on [::]:1111 as 3.
$ curl localhost:1111
Communication attempt on fd 3.
Connection from 127.0.0.1:52948 to [::ffff:127.0.0.1]:1111
Spawned cat (cat) as PID 10576.
Execing ()
Failed to execp (): No such file or directory
Child 10576 died with code 1
curl: (56) Recv failure: Connection reset by peer
```
Let's make a copy of the necessary arguments beforehand and use it
instead to fix this.