Merge pull request #15920 from keszybz/userwork-proc-title

Avoid log noise when setting proc titles and some doc updates
This commit is contained in:
Lennart Poettering 2020-05-26 18:29:06 +02:00 committed by GitHub
commit 7257f717c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 126 additions and 106 deletions

8
NEWS
View File

@ -698,10 +698,10 @@ CHANGES WITH 243:
the IO accounting data is included in the resource log message
generated whenever a unit stops.
* Units may now configure an explicit time-out to wait for when killed
* Units may now configure an explicit timeout to wait for when killed
with SIGABRT, for example when a service watchdog is hit. Previously,
the regular TimeoutStopSec= time-out was applied in this case too —
now a separate time-out may be set using TimeoutAbortSec=.
the regular TimeoutStopSec= timeout was applied in this case too —
now a separate timeout may be set using TimeoutAbortSec=.
* Services may now send a special WATCHDOG=trigger message with
sd_notify() to trigger an immediate "watchdog missed" event, and thus
@ -731,7 +731,7 @@ CHANGES WITH 243:
* If processes terminated during the last phase of shutdown do not exit
quickly systemd will now show their names after a short time, to make
debugging easier. After a longer time-out they are forcibly killed,
debugging easier. After a longer timeout they are forcibly killed,
as before.
* journalctl (and the other tools that display logs) will now highlight

View File

@ -145,7 +145,7 @@ systemd-udevd:
boot loader menu through EFI a file `/run/systemd/reboot-to-boot-loader-menu`
is created whenever this is requested. The file contains the requested boot
loader menu timeout in µs, formatted in ASCII decimals, or zero in case no
time-out is requested. This file may be checked for by services run during
timeout is requested. This file may be checked for by services run during
system shutdown in order to request the appropriate operation from the boot
loader in an alternative fashion.

View File

@ -200,7 +200,7 @@ node /org/freedesktop/home1 {
the returned error code, in case more credentials are necessary. This function is synchronous and
returns only after the home directory was fully activated (or the operation failed), which might take
some time. Clients must be prepared for that, and typically should extend the D-Bus method call
time-out accordingly. This method is equivalent to the <function>Activate()</function> method on the
timeout accordingly. This method is equivalent to the <function>Activate()</function> method on the
<classname>org.freedesktop.home1.Home</classname> interface documented below, but may be called on the
manager object and takes a user name as additional argument, instead.</para>

View File

@ -3745,7 +3745,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<varname>ActiveState</varname> above). The following values are currently known:
<literal>success</literal> is set if the unit didn't fail. <literal>resources</literal> indicates that
not enough resources were available to fork off and execute the service
processes. <literal>timeout</literal> indicates that a time-out occurred while executing a service
processes. <literal>timeout</literal> indicates that a timeout occurred while executing a service
operation. <literal>exit-code</literal> indicates that a service process exited with an unclean exit
code. <literal>signal</literal> indicates that a service process exited with an uncaught
signal. <literal>core-dump</literal> indicates that a service process exited uncleanly and dumped

View File

@ -26,7 +26,7 @@
<refname>sd_bus_get_events</refname>
<refname>sd_bus_get_timeout</refname>
<refpurpose>Get the file descriptor, I/O events and time-out to wait for from a message bus
<refpurpose>Get the file descriptor, I/O events and timeout to wait for from a message bus
object</refpurpose>
</refnamediv>
@ -79,13 +79,13 @@
<constant>POLLIN</constant>, <constant>POLLOUT</constant>, … events, or negative on error.
</para>
<para><function>sd_bus_get_timeout()</function> returns the time-out in µs to pass to to
<para><function>sd_bus_get_timeout()</function> returns the timeout in µs to pass to to
<function>poll()</function> or a similar call when waiting for events on the specified bus
connection. The returned time-out may be zero, in which case a subsequent I/O polling call
connection. The returned timeout may be zero, in which case a subsequent I/O polling call
should be invoked in non-blocking mode. The returned timeout may be
<constant>UINT64_MAX</constant> in which case the I/O polling call may block indefinitely,
without any applied time-out. Note that the returned time-out should be considered only a
maximum sleeping time. It is permissible (and even expected) that shorter time-outs are used by
without any applied timeout. Note that the returned timeout should be considered only a
maximum sleeping time. It is permissible (and even expected) that shorter timeouts are used by
the calling program, in case other event sources are polled in the same event loop. Note that
the returned time-value is relative and specified in microseconds. When converting this value in
order to pass it as third argument to <function>poll()</function> (which expects milliseconds),
@ -93,7 +93,7 @@
doesn't sleep for shorter than necessary, which might result in unintended busy looping
(alternatively, use
<citerefentry project='man-pages'><refentrytitle>ppoll</refentrytitle><manvolnum>3</manvolnum></citerefentry>
instead of plain <function>poll()</function>, which understands time-outs with nano-second
instead of plain <function>poll()</function>, which understands timeouts with nano-second
granularity).</para>
<para>These three functions are useful to hook up a bus connection object with an external or
@ -101,7 +101,7 @@
each invocation of the I/O polling call, all three functions should be invoked: the file
descriptor returned by <function>sd_bus_get_fd()</function> should be polled for the events
indicated by <function>sd_bus_get_events()</function>, and the I/O call should block for that up
to the time-out returned by <function>sd_bus_get_timeout()</function>. After each I/O polling
to the timeout returned by <function>sd_bus_get_timeout()</function>. After each I/O polling
call the bus connection needs to process incoming or outgoing data, by invoking
<citerefentry><refentrytitle>sd_bus_process</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>

View File

@ -2100,8 +2100,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<listitem>
<para>When used with the <command>reboot</command> command, indicate to the system's boot loader to show the
boot loader menu on the following boot. Takes a time value as parameter — indicating the menu time-out. Pass
zero in order to disable the menu time-out. Note that not all boot loaders support this
boot loader menu on the following boot. Takes a time value as parameter — indicating the menu timeout. Pass
zero in order to disable the menu timeout. Note that not all boot loaders support this
functionality.</para>
</listitem>
</varlistentry>

View File

@ -1098,8 +1098,8 @@ StateDirectory=aaa/bbb ccc</programlisting>
clean …</command>, see
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
details. Takes the usual time values and defaults to <constant>infinity</constant>, i.e. by default
no time-out is applied. If a time-out is configured the clean operation will be aborted forcibly when
the time-out is reached, potentially leaving resources on disk.</para></listitem>
no timeout is applied. If a timeout is configured the clean operation will be aborted forcibly when
the timeout is reached, potentially leaving resources on disk.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -571,29 +571,29 @@
<term><varname>IPAddressDeny=<replaceable>ADDRESS[/PREFIXLENGTH]…</replaceable></varname></term>
<listitem>
<para>Turn on address range network traffic filtering for IP packets sent and received over
<constant>AF_INET</constant> and <constant>AF_INET6</constant> sockets. Both directives take a
<para>Turn on network traffic filtering for IP packets sent and received over
<constant>AF_INET</constant> and <constant>AF_INET6</constant> sockets. Both directives take a
space separated list of IPv4 or IPv6 addresses, each optionally suffixed with an address prefix
length in bits (separated by a <literal>/</literal> character). If the latter is omitted, the
address is considered a host address, i.e. the prefix covers the whole address (32 for IPv4, 128
for IPv6).</para>
length in bits after a <literal>/</literal> character. If the suffix is omitted, the address is
considered a host address, i.e. the filter covers the whole address (32 bits for IPv4, 128 bits for
IPv6).</para>
<para>The access lists configured with this option are applied to all sockets created by processes
of this unit (or in the case of socket units, associated with it). The lists are implicitly
combined with any lists configured for any of the parent slice units this unit might be a member
of. By default all access lists are empty. Both ingress and egress traffic is filtered by these
of. By default both access lists are empty. Both ingress and egress traffic is filtered by these
settings. In case of ingress traffic the source IP address is checked against these access lists,
in case of egress traffic the destination IP address is checked. When configured the lists are
enforced as follows:</para>
in case of egress traffic the destination IP address is checked. The following rules are applied in
turn:</para>
<itemizedlist>
<listitem><para>Access will be granted in case an IP packet's destination/source address matches
any entry in the <varname>IPAddressAllow=</varname> setting.</para></listitem>
<listitem><para>Access is granted when the checked IP address matches an entry in the
<varname>IPAddressAllow=</varname> list.</para></listitem>
<listitem><para>Otherwise, access will be denied in case its destination/source address matches
any entry in the <varname>IPAddressDeny=</varname> setting.</para></listitem>
<listitem><para>Otherwise, access is denied when the checked IP address matches an entry in the
<varname>IPAddressDeny=</varname> list.</para></listitem>
<listitem><para>Otherwise, access will be granted.</para></listitem>
<listitem><para>Otherwise, access is granted.</para></listitem>
</itemizedlist>
<para>In order to implement a whitelisting IP firewall, it is recommended to use a
@ -604,12 +604,13 @@
details on these slice units), plus individual per-service <varname>IPAddressAllow=</varname> lines
permitting network access to relevant services, and only them.</para>
<para>Note that for socket-activated services, the IP access list configured on the socket unit applies to
all sockets associated with it directly, but not to any sockets created by the ultimately activated services
for it. Conversely, the IP access list configured for the service is not applied to any sockets passed into
the service via socket activation. Thus, it is usually a good idea, to replicate the IP access lists on both
the socket and the service unit, however it often makes sense to maintain one list more open and the other
one more restricted, depending on the usecase.</para>
<para>Note that for socket-activated services, the IP access list configured on the socket unit
applies to all sockets associated with it directly, but not to any sockets created by the
ultimately activated services for it. Conversely, the IP access list configured for the service is
not applied to any sockets passed into the service via socket activation. Thus, it is usually a
good idea to replicate the IP access lists on both the socket and the service unit. Nevertheless,
it may make sense to maintain one list more open and the other one more restricted, depending on
the usecase.</para>
<para>If these settings are used multiple times in the same unit the specified lists are combined. If an
empty string is assigned to these settings the specific access list is reset and all previous settings undone.</para>

View File

@ -464,7 +464,7 @@
of the daemon, and may be used for command lines like the
following:</para>
<programlisting>/bin/kill -HUP $MAINPID</programlisting>
<programlisting>ExecReload=kill -HUP $MAINPID</programlisting>
<para>Note however that reloading a daemon by sending a signal
(as with the example line above) is usually not a good choice,
@ -473,7 +473,14 @@
other. It is strongly recommended to set
<varname>ExecReload=</varname> to a command that not only
triggers a configuration reload of the daemon, but also
synchronously waits for it to complete.</para>
synchronously waits for it to complete. For example,
<citerefentry project='mankier'><refentrytitle>dbus-broker</refentrytitle><manvolnum>1</manvolnum></citerefentry>
uses the following:</para>
<programlisting>ExecReload=busctl call org.freedesktop.DBus \
/org/freedesktop/DBus org.freedesktop.DBus \
ReloadConfig
</programlisting>
</listitem>
</varlistentry>

View File

@ -206,50 +206,12 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
return 0;
}
int rename_process(const char name[]) {
static size_t mm_size = 0;
static char *mm = NULL;
bool truncated = false;
size_t l;
static int update_argv(const char name[], size_t l) {
static int can_do = -1;
/* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's
* internally used name of the process. For the first one a limit of 16 chars applies; to the second one in
* many cases one of 10 (i.e. length of "/sbin/init") however if we have CAP_SYS_RESOURCES it is unbounded;
* to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be
* truncated.
*
* Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */
if (isempty(name))
return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
if (!is_main_thread())
return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we
* cache things without locking, and we make assumptions that PR_SET_NAME sets the
* process name that isn't correct on any other threads */
l = strlen(name);
/* First step, change the comm field. The main thread's comm is identical to the process comm. This means we
* can use PR_SET_NAME, which sets the thread name for the calling thread. */
if (prctl(PR_SET_NAME, name) < 0)
log_debug_errno(errno, "PR_SET_NAME failed: %m");
if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */
truncated = true;
/* Second step, change glibc's ID of the process name. */
if (program_invocation_name) {
size_t k;
k = strlen(program_invocation_name);
strncpy(program_invocation_name, name, k);
if (l > k)
truncated = true;
}
/* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but
* has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at
* the end. This is the best option for changing /proc/self/cmdline. */
if (can_do == 0)
return 0;
can_do = false; /* We'll set it to true only if the whole process works */
/* Let's not bother with this if we don't have euid == 0. Strictly speaking we should check for the
* CAP_SYS_RESOURCE capability which is independent of the euid. In our own code the capability generally is
@ -257,22 +219,29 @@ int rename_process(const char name[]) {
* PR_SET_MM_ARG_{START,END} fails with EPERM later on anyway. After all geteuid() is dead cheap to call, but
* mmap() is not. */
if (geteuid() != 0)
log_debug("Skipping PR_SET_MM, as we don't have privileges.");
else if (mm_size < l+1) {
return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
"Skipping PR_SET_MM, as we don't have privileges.");
static size_t mm_size = 0;
static char *mm = NULL;
int r;
if (mm_size < l+1) {
size_t nn_size;
char *nn;
nn_size = PAGE_ALIGN(l+1);
nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (nn == MAP_FAILED) {
log_debug_errno(errno, "mmap() failed: %m");
goto use_saved_argv;
}
if (nn == MAP_FAILED)
return log_debug_errno(errno, "mmap() failed: %m");
strncpy(nn, name, nn_size);
/* Now, let's tell the kernel about this new memory */
if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
if (ERRNO_IS_PRIVILEGE(errno))
return log_debug_errno(errno, "PR_SET_MM_ARG_START failed: %m");
/* HACK: prctl() API is kind of dumb on this point. The existing end address may already be
* below the desired start address, in which case the kernel may have kicked this back due
* to a range-check failure (see linux/kernel/sys.c:validate_prctl_map() to see this in
@ -284,15 +253,13 @@ int rename_process(const char name[]) {
log_debug_errno(errno, "PR_SET_MM_ARG_START failed, attempting PR_SET_MM_ARG_END hack: %m");
if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) {
log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m");
r = log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m");
(void) munmap(nn, nn_size);
goto use_saved_argv;
return r;
}
if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m");
goto use_saved_argv;
}
if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0)
return log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m");
} else {
/* And update the end pointer to the new end, too. If this fails, we don't really know what
* to do, it's pretty unlikely that we can rollback, hence we'll just accept the failure,
@ -314,13 +281,56 @@ int rename_process(const char name[]) {
log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
}
use_saved_argv:
can_do = true;
return 0;
}
int rename_process(const char name[]) {
bool truncated = false;
/* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's
* internally used name of the process. For the first one a limit of 16 chars applies; to the second one in
* many cases one of 10 (i.e. length of "/sbin/init") however if we have CAP_SYS_RESOURCES it is unbounded;
* to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be
* truncated.
*
* Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */
if (isempty(name))
return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
if (!is_main_thread())
return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we
* cache things without locking, and we make assumptions that PR_SET_NAME sets the
* process name that isn't correct on any other threads */
size_t l = strlen(name);
/* First step, change the comm field. The main thread's comm is identical to the process comm. This means we
* can use PR_SET_NAME, which sets the thread name for the calling thread. */
if (prctl(PR_SET_NAME, name) < 0)
log_debug_errno(errno, "PR_SET_NAME failed: %m");
if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */
truncated = true;
/* Second step, change glibc's ID of the process name. */
if (program_invocation_name) {
size_t k;
k = strlen(program_invocation_name);
strncpy(program_invocation_name, name, k);
if (l > k)
truncated = true;
}
/* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but
* has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at
* the end. This is the best option for changing /proc/self/cmdline. */
(void) update_argv(name, l);
/* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if
* it still looks here */
if (saved_argc > 0) {
int i;
if (saved_argv[0]) {
size_t k;
@ -330,7 +340,7 @@ use_saved_argv:
truncated = true;
}
for (i = 1; i < saved_argc; i++) {
for (int i = 1; i < saved_argc; i++) {
if (!saved_argv[i])
break;

View File

@ -19,7 +19,7 @@ int split_user_name_realm(const char *t, char **ret_user_name, char **ret_realm)
int bus_message_append_secret(sd_bus_message *m, UserRecord *secret);
/* Many of our operations might be slow due to crypto, fsck, recursive chown() and so on. For these
* operations permit a *very* long time-out */
* operations permit a *very* long timeout */
#define HOME_SLOW_BUS_CALL_TIMEOUT_USEC (2*USEC_PER_MINUTE)
int test_password_one(const char *hashed_password, const char *password);

View File

@ -1718,7 +1718,7 @@ static int wait_for_devlink(const char *path) {
usec_t until;
int r;
/* let's wait for a device link to show up in /dev, with a time-out. This is good to do since we
/* let's wait for a device link to show up in /dev, with a timeout. This is good to do since we
* return a /dev/disk/by-uuid/ link to our callers and they likely want to access it right-away,
* hence let's wait until udev has caught up with our changes, and wait for the symlink to be
* created. */

View File

@ -134,7 +134,7 @@ int nscd_flush_cache(char **databases) {
int r = 0;
char **i;
/* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s time-out, so that we
/* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s timeout, so that we
* don't block indefinitely on another service. */
end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC);

View File

@ -715,7 +715,8 @@ static int run(int argc, char *argv[]) {
n = now(CLOCK_MONOTONIC);
if (n >= usec_add(start_time, RUNTIME_MAX_USEC)) {
char buf[FORMAT_TIMESPAN_MAX];
log_debug("Exiting worker, ran for %s, that's enough.", format_timespan(buf, sizeof(buf), usec_sub_unsigned(n, start_time), 0));
log_debug("Exiting worker, ran for %s, that's enough.",
format_timespan(buf, sizeof(buf), usec_sub_unsigned(n, start_time), 0));
break;
}
@ -723,7 +724,8 @@ static int run(int argc, char *argv[]) {
last_busy_usec = n;
else if (listen_idle_usec != USEC_INFINITY && n >= usec_add(last_busy_usec, listen_idle_usec)) {
char buf[FORMAT_TIMESPAN_MAX];
log_debug("Exiting worker, been idle for %s, .", format_timespan(buf, sizeof(buf), usec_sub_unsigned(n, last_busy_usec), 0));
log_debug("Exiting worker, been idle for %s, .",
format_timespan(buf, sizeof(buf), usec_sub_unsigned(n, last_busy_usec), 0));
break;
}
@ -736,7 +738,7 @@ static int run(int argc, char *argv[]) {
(void) rename_process("systemd-userwork: processing...");
if (fd == -EAGAIN)
continue; /* The listening socket as SO_RECVTIMEO set, hence a time-out is expected
continue; /* The listening socket has SO_RECVTIMEO set, hence a timeout is expected
* after a while, let's check if it's time to exit though. */
if (fd == -EINTR)
continue; /* Might be that somebody attached via strace, let's just continue in that

View File

@ -26,5 +26,5 @@ ExecStop=@rootlibexecdir@/systemd-random-seed save
# This service waits until the kernel's entropy pool is initialized, and may be
# used as ordering barrier for service that require an initialized entropy
# pool. Since initialization can take a while on entropy-starved systems, let's
# increase the time-out substantially here.
# increase the timeout substantially here.
TimeoutSec=10min