mirror of
https://github.com/systemd/systemd
synced 2025-12-22 17:04:45 +01:00
Compare commits
15 Commits
20367ade71
...
65d173a02d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65d173a02d | ||
|
|
6dcc937568 | ||
|
|
8a10293e5d | ||
|
|
f3c6660b9c | ||
|
|
72ce1046e8 | ||
|
|
eb17c37df7 | ||
|
|
4dcbfbb1ad | ||
|
|
84dcbc3fd2 | ||
|
|
27de9c391d | ||
|
|
29d1df4b03 | ||
|
|
fbd276cb86 | ||
|
|
e74b571004 | ||
|
|
9bd833ee6e | ||
|
|
8c367868ee | ||
|
|
a1e5d7f865 |
4
TODO
4
TODO
@ -576,10 +576,6 @@ Features:
|
|||||||
* The bind(AF_UNSPEC) construct (for resetting sockets to their initial state)
|
* The bind(AF_UNSPEC) construct (for resetting sockets to their initial state)
|
||||||
should be blocked in many cases because it punches holes in many sandboxes.
|
should be blocked in many cases because it punches holes in many sandboxes.
|
||||||
|
|
||||||
* find a nice way to opt-in into auto-masking SIGCHLD on first
|
|
||||||
sd_event_add_child(), and then get rid of many more explicit sigprocmask()
|
|
||||||
calls.
|
|
||||||
|
|
||||||
* introduce new structure Tpm2CombinedPolicy, that combines the various TPm2
|
* introduce new structure Tpm2CombinedPolicy, that combines the various TPm2
|
||||||
policy bits into one structure, i.e. public key info, pcr masks, pcrlock
|
policy bits into one structure, i.e. public key info, pcr masks, pcrlock
|
||||||
stuff, pin and so on. Then pass that around in tpm2_seal() and tpm2_unseal().
|
stuff, pin and so on. Then pass that around in tpm2_seal() and tpm2_unseal().
|
||||||
|
|||||||
@ -10,12 +10,6 @@ int main(int argc, char **argv) {
|
|||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
assert(pid >= 0);
|
assert(pid >= 0);
|
||||||
|
|
||||||
/* SIGCHLD signal must be blocked for sd_event_add_child to work */
|
|
||||||
sigset_t ss;
|
|
||||||
sigemptyset(&ss);
|
|
||||||
sigaddset(&ss, SIGCHLD);
|
|
||||||
sigprocmask(SIG_BLOCK, &ss, NULL);
|
|
||||||
|
|
||||||
if (pid == 0) /* child */
|
if (pid == 0) /* child */
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
|
|||||||
@ -149,11 +149,13 @@
|
|||||||
<constant>SD_EVENT_OFF</constant> with
|
<constant>SD_EVENT_OFF</constant> with
|
||||||
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
<citerefentry><refentrytitle>sd_event_source_set_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
<para>The <constant>SIGCHLD</constant> signal must be blocked in all threads before this function is
|
<para>The kernel autoreaping logic must be disabled for this function to work as expected (see
|
||||||
called (using <citerefentry
|
<citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>).</para>
|
||||||
project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry> or
|
|
||||||
<citerefentry
|
<para>When watching for <constant>WSTOPPED</constant> or <constant>WCONTINUED</constant>, the
|
||||||
project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
|
<constant>SIGCHLD</constant> signal must be blocked in all threads before this function is called (using
|
||||||
|
<citerefentry project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry> or
|
||||||
|
<citerefentry project='man-pages'><refentrytitle>pthread_sigmask</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para>
|
||||||
|
|
||||||
<para>If the second parameter of <function>sd_event_add_child()</function> is passed as
|
<para>If the second parameter of <function>sd_event_add_child()</function> is passed as
|
||||||
<constant>NULL</constant> no reference to the event source object is returned. In this case, the event
|
<constant>NULL</constant> no reference to the event source object is returned. In this case, the event
|
||||||
@ -190,7 +192,9 @@
|
|||||||
regardless which of <function>sd_event_add_child()</function> and
|
regardless which of <function>sd_event_add_child()</function> and
|
||||||
<function>sd_event_add_child_pidfd()</function> is used for allocating an event source, the watched
|
<function>sd_event_add_child_pidfd()</function> is used for allocating an event source, the watched
|
||||||
process has to be a direct child process of the invoking process. Also in both cases
|
process has to be a direct child process of the invoking process. Also in both cases
|
||||||
<constant>SIGCHLD</constant> has to be blocked in the invoking process.</para>
|
<constant>SIGCHLD</constant> has to be blocked in the invoking process when watching for
|
||||||
|
<constant>WSTOPPED</constant> or <constant>WCONTINUED</constant> and the kernel autoreaping logic has to
|
||||||
|
be disabled.</para>
|
||||||
|
|
||||||
<para><function>sd_event_source_get_child_pid()</function>
|
<para><function>sd_event_source_get_child_pid()</function>
|
||||||
retrieves the configured PID of a child process state change event
|
retrieves the configured PID of a child process state change event
|
||||||
|
|||||||
@ -1326,7 +1326,7 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
|||||||
<term><varname>CPUSchedulingPolicy=</varname></term>
|
<term><varname>CPUSchedulingPolicy=</varname></term>
|
||||||
|
|
||||||
<listitem><para>Sets the CPU scheduling policy for executed processes. Takes one of <option>other</option>,
|
<listitem><para>Sets the CPU scheduling policy for executed processes. Takes one of <option>other</option>,
|
||||||
<option>batch</option>, <option>idle</option>, <option>fifo</option> or <option>rr</option>. See
|
<option>batch</option>, <option>idle</option>, <option>fifo</option>, <option>rr</option> or <option>ext</option>. See
|
||||||
<citerefentry project='man-pages'><refentrytitle>sched_setscheduler</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
|
<citerefentry project='man-pages'><refentrytitle>sched_setscheduler</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
|
||||||
details.</para></listitem>
|
details.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|||||||
13
meson.build
13
meson.build
@ -2948,7 +2948,18 @@ endif
|
|||||||
alias_target('gensources', generated_sources)
|
alias_target('gensources', generated_sources)
|
||||||
|
|
||||||
clang_tidy = find_program('clang-tidy', required : false)
|
clang_tidy = find_program('clang-tidy', required : false)
|
||||||
if meson.version().version_compare('>=1.4.0')
|
if meson.version().version_compare('>=1.10.0')
|
||||||
|
uniq = {}
|
||||||
|
|
||||||
|
foreach source : sources
|
||||||
|
if uniq.has_key(source.full_path())
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
uniq += {source.full_path(): source}
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
sources = uniq.values()
|
||||||
|
|
||||||
foreach source : sources
|
foreach source : sources
|
||||||
if systemd_headers.contains(source)
|
if systemd_headers.contains(source)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
#include "lock-util.h"
|
#include "lock-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
@ -199,7 +200,6 @@ int lock_generic(int fd, LockType type, int operation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeout) {
|
int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeout) {
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
@ -223,8 +223,8 @@ int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeo
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* If that didn't work, try with a child */
|
/* If that didn't work, try with a child */
|
||||||
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
r = safe_fork("(sd-flock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid);
|
r = pidref_safe_fork("(sd-flock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to flock block device in child process: %m");
|
return log_error_errno(r, "Failed to flock block device in child process: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -256,11 +256,11 @@ int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeo
|
|||||||
}
|
}
|
||||||
|
|
||||||
siginfo_t status;
|
siginfo_t status;
|
||||||
r = wait_for_terminate(pid, &status);
|
r = pidref_wait_for_terminate(&pidref, &status);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
TAKE_PID(pid);
|
pidref_done(&pidref);
|
||||||
|
|
||||||
switch (status.si_code) {
|
switch (status.si_code) {
|
||||||
|
|
||||||
|
|||||||
@ -601,25 +601,25 @@ int userns_acquire_self_root(void) {
|
|||||||
return userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true);
|
return userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int userns_enter_and_pin(int userns_fd, pid_t *ret_pid) {
|
int userns_enter_and_pin(int userns_fd, PidRef *ret) {
|
||||||
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
char x;
|
char x;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(userns_fd >= 0);
|
assert(userns_fd >= 0);
|
||||||
assert(ret_pid);
|
assert(ret);
|
||||||
|
|
||||||
if (pipe2(pfd, O_CLOEXEC) < 0)
|
if (pipe2(pfd, O_CLOEXEC) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = safe_fork_full(
|
r = pidref_safe_fork_full(
|
||||||
"(sd-pinuserns)",
|
"(sd-pinuserns)",
|
||||||
/* stdio_fds= */ NULL,
|
/* stdio_fds= */ NULL,
|
||||||
(int[]) { pfd[1], userns_fd }, 2,
|
(int[]) { pfd[1], userns_fd }, 2,
|
||||||
FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
|
FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
|
||||||
&pid);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -652,7 +652,7 @@ int userns_enter_and_pin(int userns_fd, pid_t *ret_pid) {
|
|||||||
assert(n == 1);
|
assert(n == 1);
|
||||||
assert(x == 'x');
|
assert(x == 'x');
|
||||||
|
|
||||||
*ret_pid = TAKE_PID(pid);
|
*ret = TAKE_PIDREF(pidref);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,22 +661,22 @@ bool userns_supported(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
|
int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(userns_fd >= 0);
|
assert(userns_fd >= 0);
|
||||||
|
|
||||||
r = userns_enter_and_pin(userns_fd, &pid);
|
r = userns_enter_and_pin(userns_fd, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
r = uid_map_search_root(pid, UID_RANGE_USERNS_OUTSIDE, &uid);
|
r = uid_map_search_root(pidref.pid, UID_RANGE_USERNS_OUTSIDE, &uid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
r = uid_map_search_root(pid, GID_RANGE_USERNS_OUTSIDE, &gid);
|
r = uid_map_search_root(pidref.pid, GID_RANGE_USERNS_OUTSIDE, &gid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,7 @@ int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_r
|
|||||||
int userns_acquire_empty(void);
|
int userns_acquire_empty(void);
|
||||||
int userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny);
|
int userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny);
|
||||||
int userns_acquire_self_root(void);
|
int userns_acquire_self_root(void);
|
||||||
int userns_enter_and_pin(int userns_fd, pid_t *ret_pid);
|
int userns_enter_and_pin(int userns_fd, PidRef *ret);
|
||||||
bool userns_supported(void);
|
bool userns_supported(void);
|
||||||
|
|
||||||
int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid);
|
int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -8,12 +9,14 @@
|
|||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "hash-funcs.h"
|
#include "hash-funcs.h"
|
||||||
|
#include "io-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "pidfd-util.h"
|
#include "pidfd-util.h"
|
||||||
#include "pidref.h"
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "siphash24.h"
|
#include "siphash24.h"
|
||||||
|
#include "time-util.h"
|
||||||
|
|
||||||
int pidref_acquire_pidfd_id(PidRef *pidref) {
|
int pidref_acquire_pidfd_id(PidRef *pidref) {
|
||||||
int r;
|
int r;
|
||||||
@ -449,9 +452,11 @@ bool pidref_is_self(PidRef *pidref) {
|
|||||||
return pidref->fd_id == self_id;
|
return pidref->fd_id == self_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pidref_wait(PidRef *pidref, siginfo_t *ret, int options) {
|
int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *ret_si) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(timeout > 0);
|
||||||
|
|
||||||
if (!pidref_is_set(pidref))
|
if (!pidref_is_set(pidref))
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
|
|
||||||
@ -461,25 +466,37 @@ int pidref_wait(PidRef *pidref, siginfo_t *ret, int options) {
|
|||||||
if (pidref->pid == 1 || pidref_is_self(pidref))
|
if (pidref->pid == 1 || pidref_is_self(pidref))
|
||||||
return -ECHILD;
|
return -ECHILD;
|
||||||
|
|
||||||
siginfo_t si = {};
|
if (timeout != USEC_INFINITY && pidref->fd < 0)
|
||||||
if (pidref->fd >= 0)
|
return -ENOMEDIUM;
|
||||||
r = RET_NERRNO(waitid(P_PIDFD, pidref->fd, &si, options));
|
|
||||||
else
|
|
||||||
r = RET_NERRNO(waitid(P_PID, pidref->pid, &si, options));
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (ret)
|
usec_t ts = timeout == USEC_INFINITY ? USEC_INFINITY : usec_add(now(CLOCK_MONOTONIC), timeout);
|
||||||
*ret = si;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
r = pidref_wait(pidref, ret, WEXITED);
|
if (ts != USEC_INFINITY) {
|
||||||
|
usec_t left = usec_sub_unsigned(ts, now(CLOCK_MONOTONIC));
|
||||||
|
if (left == 0)
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
|
||||||
|
r = fd_wait_for_event(pidref->fd, POLLIN, left);
|
||||||
|
if (r == 0)
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
if (r == -EINTR)
|
||||||
|
continue;
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
siginfo_t si = {};
|
||||||
|
|
||||||
|
if (pidref->fd >= 0)
|
||||||
|
r = RET_NERRNO(waitid(P_PIDFD, pidref->fd, &si, WEXITED));
|
||||||
|
else
|
||||||
|
r = RET_NERRNO(waitid(P_PID, pidref->pid, &si, WEXITED));
|
||||||
|
if (r >= 0) {
|
||||||
|
if (ret_si)
|
||||||
|
*ret_si = si;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (r != -EINTR)
|
if (r != -EINTR)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,8 +96,19 @@ int pidref_kill(const PidRef *pidref, int sig);
|
|||||||
int pidref_kill_and_sigcont(const PidRef *pidref, int sig);
|
int pidref_kill_and_sigcont(const PidRef *pidref, int sig);
|
||||||
int pidref_sigqueue(const PidRef *pidref, int sig, int value);
|
int pidref_sigqueue(const PidRef *pidref, int sig, int value);
|
||||||
|
|
||||||
int pidref_wait(PidRef *pidref, siginfo_t *ret, int options);
|
int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *ret_si);
|
||||||
int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret);
|
static inline int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret_si) {
|
||||||
|
return pidref_wait_for_terminate_full(pidref, USEC_INFINITY, ret_si);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pidref_done_sigterm_wait(PidRef *pidref) {
|
||||||
|
if (!pidref_is_set(pidref))
|
||||||
|
return;
|
||||||
|
|
||||||
|
(void) pidref_kill(pidref, SIGTERM);
|
||||||
|
(void) pidref_wait_for_terminate(pidref, NULL);
|
||||||
|
pidref_done(pidref);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void pidref_done_sigkill_wait(PidRef *pidref) {
|
static inline void pidref_done_sigkill_wait(PidRef *pidref) {
|
||||||
if (!pidref_is_set(pidref))
|
if (!pidref_is_set(pidref))
|
||||||
@ -108,6 +119,14 @@ static inline void pidref_done_sigkill_wait(PidRef *pidref) {
|
|||||||
pidref_done(pidref);
|
pidref_done(pidref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void pidref_done_sigkill_nowait(PidRef *pidref) {
|
||||||
|
if (!pidref_is_set(pidref))
|
||||||
|
return;
|
||||||
|
|
||||||
|
(void) pidref_kill(pidref, SIGKILL);
|
||||||
|
pidref_done(pidref);
|
||||||
|
}
|
||||||
|
|
||||||
int pidref_verify(const PidRef *pidref);
|
int pidref_verify(const PidRef *pidref);
|
||||||
|
|
||||||
#define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
|
#define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
|
||||||
|
|||||||
@ -845,13 +845,9 @@ int get_process_umask(pid_t pid, mode_t *ret) {
|
|||||||
return parse_mode(m, ret);
|
return parse_mode(m, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int wait_for_terminate(pid_t pid, siginfo_t *ret) {
|
|
||||||
return pidref_wait_for_terminate(&PIDREF_MAKE_FROM_PID(pid), ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return values:
|
* Return values:
|
||||||
* < 0 : wait_for_terminate() failed to get the state of the
|
* < 0 : pidref_wait_for_terminate() failed to get the state of the
|
||||||
* process, the process was terminated by a signal, or
|
* process, the process was terminated by a signal, or
|
||||||
* failed for an unknown reason.
|
* failed for an unknown reason.
|
||||||
* >=0 : The process terminated normally, and its exit code is
|
* >=0 : The process terminated normally, and its exit code is
|
||||||
@ -908,115 +904,6 @@ int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFl
|
|||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
|
|
||||||
return pidref_wait_for_terminate_and_check(name, &PIDREF_MAKE_FROM_PID(pid), flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return values:
|
|
||||||
*
|
|
||||||
* < 0 : wait_for_terminate_with_timeout() failed to get the state of the process, the process timed out, the process
|
|
||||||
* was terminated by a signal, or failed for an unknown reason.
|
|
||||||
*
|
|
||||||
* >=0 : The process terminated normally with no failures.
|
|
||||||
*
|
|
||||||
* Success is indicated by a return value of zero, a timeout is indicated by ETIMEDOUT, and all other child failure
|
|
||||||
* states are indicated by error is indicated by a non-zero value.
|
|
||||||
*
|
|
||||||
* This call assumes SIGCHLD has been blocked already, in particular before the child to wait for has been forked off
|
|
||||||
* to remain entirely race-free.
|
|
||||||
*/
|
|
||||||
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
|
|
||||||
sigset_t mask;
|
|
||||||
int r;
|
|
||||||
usec_t until;
|
|
||||||
|
|
||||||
assert_se(sigemptyset(&mask) == 0);
|
|
||||||
assert_se(sigaddset(&mask, SIGCHLD) == 0);
|
|
||||||
|
|
||||||
/* Drop into a sigtimewait-based timeout. Waiting for the
|
|
||||||
* pid to exit. */
|
|
||||||
until = usec_add(now(CLOCK_MONOTONIC), timeout);
|
|
||||||
for (;;) {
|
|
||||||
usec_t n;
|
|
||||||
siginfo_t status = {};
|
|
||||||
|
|
||||||
n = now(CLOCK_MONOTONIC);
|
|
||||||
if (n >= until)
|
|
||||||
break;
|
|
||||||
|
|
||||||
r = RET_NERRNO(sigtimedwait(&mask, NULL, TIMESPEC_STORE(until - n)));
|
|
||||||
/* Assuming we woke due to the child exiting. */
|
|
||||||
if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) {
|
|
||||||
if (status.si_pid == pid) {
|
|
||||||
/* This is the correct child. */
|
|
||||||
if (status.si_code == CLD_EXITED)
|
|
||||||
return status.si_status == 0 ? 0 : -EPROTO;
|
|
||||||
else
|
|
||||||
return -EPROTO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Not the child, check for errors and proceed appropriately */
|
|
||||||
if (r < 0) {
|
|
||||||
switch (r) {
|
|
||||||
case -EAGAIN:
|
|
||||||
/* Timed out, child is likely hung. */
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
case -EINTR:
|
|
||||||
/* Received a different signal and should retry */
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
/* Return any unexpected errors */
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EPROTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sigkill_wait(pid_t pid) {
|
|
||||||
assert(pid > 1);
|
|
||||||
|
|
||||||
(void) kill(pid, SIGKILL);
|
|
||||||
(void) wait_for_terminate(pid, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sigkill_waitp(pid_t *pid) {
|
|
||||||
PROTECT_ERRNO;
|
|
||||||
|
|
||||||
if (!pid)
|
|
||||||
return;
|
|
||||||
if (*pid <= 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sigkill_wait(*pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sigterm_wait(pid_t pid) {
|
|
||||||
assert(pid > 1);
|
|
||||||
|
|
||||||
(void) kill_and_sigcont(pid, SIGTERM);
|
|
||||||
(void) wait_for_terminate(pid, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sigkill_nowait(pid_t pid) {
|
|
||||||
assert(pid > 1);
|
|
||||||
|
|
||||||
(void) kill(pid, SIGKILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sigkill_nowaitp(pid_t *pid) {
|
|
||||||
PROTECT_ERRNO;
|
|
||||||
|
|
||||||
if (!pid)
|
|
||||||
return;
|
|
||||||
if (*pid <= 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sigkill_nowait(*pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
int kill_and_sigcont(pid_t pid, int sig) {
|
int kill_and_sigcont(pid_t pid, int sig) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1343,7 +1230,9 @@ void valgrind_summary_hack(void) {
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
else {
|
else {
|
||||||
log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
|
log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
|
||||||
(void) wait_for_terminate(pid, NULL);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid);
|
||||||
|
(void) pidref_set_pid(&pidref, pid);
|
||||||
|
(void) pidref_wait_for_terminate(&pidref, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1359,11 +1248,33 @@ bool nice_is_valid(int n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool sched_policy_is_valid(int i) {
|
bool sched_policy_is_valid(int i) {
|
||||||
return IN_SET(i, SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR);
|
return IN_SET(i, SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR, SCHED_EXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sched_priority_is_valid(int i) {
|
bool sched_policy_supported(int policy) {
|
||||||
return i >= 0 && i <= sched_get_priority_max(SCHED_RR);
|
return sched_get_priority_min(policy) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrappers around sched_get_priority_{min,max}() that gracefully handles missing SCHED_EXT support in the kernel */
|
||||||
|
int sched_get_priority_min_safe(int policy) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = sched_get_priority_min(policy);
|
||||||
|
if (r >= 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* Fallback priority */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sched_get_priority_max_safe(int policy) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = sched_get_priority_max(policy);
|
||||||
|
if (r >= 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The cached PID, possible values:
|
/* The cached PID, possible values:
|
||||||
@ -1566,9 +1477,13 @@ int pidref_safe_fork_full(
|
|||||||
pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
|
pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
|
||||||
|
|
||||||
if (pidref_transport_fds[0] >= 0) {
|
if (pidref_transport_fds[0] >= 0) {
|
||||||
/* Wait for the intermediary child to exit so the caller can be certain the actual child
|
/* Wait for the intermediary child to exit so the caller can be
|
||||||
* process has been reparented by the time this function returns. */
|
* certain the actual child process has been reparented by the time
|
||||||
r = wait_for_terminate_and_check(name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
|
* this function returns. */
|
||||||
|
r = pidref_wait_for_terminate_and_check(
|
||||||
|
name,
|
||||||
|
&PIDREF_MAKE_FROM_PID(pid),
|
||||||
|
FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_full_errno(prio, r, "Failed to wait for intermediary process: %m");
|
return log_full_errno(prio, r, "Failed to wait for intermediary process: %m");
|
||||||
if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
|
if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
|
||||||
@ -1644,7 +1559,10 @@ int pidref_safe_fork_full(
|
|||||||
(void) sigprocmask(SIG_SETMASK, &ss, NULL);
|
(void) sigprocmask(SIG_SETMASK, &ss, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
|
r = pidref_wait_for_terminate_and_check(
|
||||||
|
name,
|
||||||
|
&PIDREF_MAKE_FROM_PID(pid),
|
||||||
|
FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
|
if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
|
||||||
@ -2361,9 +2279,10 @@ DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
|
|||||||
static const char* const sched_policy_table[] = {
|
static const char* const sched_policy_table[] = {
|
||||||
[SCHED_OTHER] = "other",
|
[SCHED_OTHER] = "other",
|
||||||
[SCHED_BATCH] = "batch",
|
[SCHED_BATCH] = "batch",
|
||||||
[SCHED_IDLE] = "idle",
|
[SCHED_IDLE] = "idle",
|
||||||
[SCHED_FIFO] = "fifo",
|
[SCHED_FIFO] = "fifo",
|
||||||
[SCHED_RR] = "rr",
|
[SCHED_EXT] = "ext",
|
||||||
|
[SCHED_RR] = "rr",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
|
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
|
||||||
|
|||||||
@ -60,8 +60,6 @@ static inline bool SIGINFO_CODE_IS_DEAD(int code) {
|
|||||||
return IN_SET(code, CLD_EXITED, CLD_KILLED, CLD_DUMPED);
|
return IN_SET(code, CLD_EXITED, CLD_KILLED, CLD_DUMPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
int wait_for_terminate(pid_t pid, siginfo_t *ret);
|
|
||||||
|
|
||||||
typedef enum WaitFlags {
|
typedef enum WaitFlags {
|
||||||
WAIT_LOG_ABNORMAL = 1 << 0,
|
WAIT_LOG_ABNORMAL = 1 << 0,
|
||||||
WAIT_LOG_NON_ZERO_EXIT_STATUS = 1 << 1,
|
WAIT_LOG_NON_ZERO_EXIT_STATUS = 1 << 1,
|
||||||
@ -71,15 +69,6 @@ typedef enum WaitFlags {
|
|||||||
} WaitFlags;
|
} WaitFlags;
|
||||||
|
|
||||||
int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFlags flags);
|
int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFlags flags);
|
||||||
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags);
|
|
||||||
|
|
||||||
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout);
|
|
||||||
|
|
||||||
void sigkill_wait(pid_t pid);
|
|
||||||
void sigkill_waitp(pid_t *pid);
|
|
||||||
void sigterm_wait(pid_t pid);
|
|
||||||
void sigkill_nowait(pid_t pid);
|
|
||||||
void sigkill_nowaitp(pid_t *pid);
|
|
||||||
|
|
||||||
int kill_and_sigcont(pid_t pid, int sig);
|
int kill_and_sigcont(pid_t pid, int sig);
|
||||||
|
|
||||||
@ -139,7 +128,9 @@ int pid_compare_func(const pid_t *a, const pid_t *b);
|
|||||||
bool nice_is_valid(int n) _const_;
|
bool nice_is_valid(int n) _const_;
|
||||||
|
|
||||||
bool sched_policy_is_valid(int i) _const_;
|
bool sched_policy_is_valid(int i) _const_;
|
||||||
bool sched_priority_is_valid(int i) _const_;
|
bool sched_policy_supported(int i);
|
||||||
|
int sched_get_priority_min_safe(int i);
|
||||||
|
int sched_get_priority_max_safe(int i);
|
||||||
|
|
||||||
#define PID_AUTOMATIC ((pid_t) INT_MIN) /* special value indicating "acquire pid from connection peer" */
|
#define PID_AUTOMATIC ((pid_t) INT_MIN) /* special value indicating "acquire pid from connection peer" */
|
||||||
|
|
||||||
|
|||||||
@ -238,6 +238,15 @@ int signal_is_blocked(int sig) {
|
|||||||
return RET_NERRNO(sigismember(&ss, sig));
|
return RET_NERRNO(sigismember(&ss, sig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int autoreaping_enabled(void) {
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
if (sigaction(SIGCHLD, /* __act= */ NULL, &sa) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return sa.sa_handler == SIG_IGN || FLAGS_SET(sa.sa_flags, SA_NOCLDWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
int pop_pending_signal_internal(int sig, ...) {
|
int pop_pending_signal_internal(int sig, ...) {
|
||||||
sigset_t ss;
|
sigset_t ss;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|||||||
@ -66,6 +66,8 @@ static inline const char* signal_to_string_with_check(int n) {
|
|||||||
|
|
||||||
int signal_is_blocked(int sig);
|
int signal_is_blocked(int sig);
|
||||||
|
|
||||||
|
int autoreaping_enabled(void);
|
||||||
|
|
||||||
int pop_pending_signal_internal(int sig, ...);
|
int pop_pending_signal_internal(int sig, ...);
|
||||||
#define pop_pending_signal(...) pop_pending_signal_internal(__VA_ARGS__, -1)
|
#define pop_pending_signal(...) pop_pending_signal_internal(__VA_ARGS__, -1)
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "namespace-util.h"
|
#include "namespace-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "sort-util.h"
|
#include "sort-util.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
@ -286,7 +287,7 @@ int uid_range_load_userns(const char *path, UIDRangeUsernsMode mode, UIDRange **
|
|||||||
}
|
}
|
||||||
|
|
||||||
int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange **ret) {
|
int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange **ret) {
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(userns_fd >= 0);
|
assert(userns_fd >= 0);
|
||||||
@ -294,12 +295,12 @@ int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange
|
|||||||
assert(mode < _UID_RANGE_USERNS_MODE_MAX);
|
assert(mode < _UID_RANGE_USERNS_MODE_MAX);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
r = userns_enter_and_pin(userns_fd, &pid);
|
r = userns_enter_and_pin(userns_fd, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
const char *p = procfs_file_alloca(
|
const char *p = procfs_file_alloca(
|
||||||
pid,
|
pidref.pid,
|
||||||
IN_SET(mode, UID_RANGE_USERNS_INSIDE, UID_RANGE_USERNS_OUTSIDE) ? "uid_map" : "gid_map");
|
IN_SET(mode, UID_RANGE_USERNS_INSIDE, UID_RANGE_USERNS_OUTSIDE) ? "uid_map" : "gid_map");
|
||||||
|
|
||||||
return uid_range_load_userns(p, mode, ret);
|
return uid_range_load_userns(p, mode, ret);
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "raw-clone.h"
|
#include "raw-clone.h"
|
||||||
#include "rlimit-util.h"
|
#include "rlimit-util.h"
|
||||||
@ -127,8 +128,11 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) {
|
|||||||
LOG_MESSAGE_ID(SD_MESSAGE_CRASH_PROCESS_SIGNAL_STR));
|
LOG_MESSAGE_ID(SD_MESSAGE_CRASH_PROCESS_SIGNAL_STR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid);
|
||||||
|
(void) pidref_set_pid(&pidref, pid);
|
||||||
|
|
||||||
/* Order things nicely. */
|
/* Order things nicely. */
|
||||||
r = wait_for_terminate(pid, &status);
|
r = pidref_wait_for_terminate(&pidref, &status);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_struct_errno(LOG_EMERG, r,
|
log_struct_errno(LOG_EMERG, r,
|
||||||
LOG_MESSAGE("Caught <%s>, waitpid() failed: %m", signal_to_string(sig)),
|
LOG_MESSAGE("Caught <%s>, waitpid() failed: %m", signal_to_string(sig)),
|
||||||
@ -181,7 +185,9 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) {
|
|||||||
_exit(EXIT_EXCEPTION);
|
_exit(EXIT_EXCEPTION);
|
||||||
} else {
|
} else {
|
||||||
log_info("Spawned crash shell as PID "PID_FMT".", pid);
|
log_info("Spawned crash shell as PID "PID_FMT".", pid);
|
||||||
(void) wait_for_terminate(pid, NULL);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid);
|
||||||
|
(void) pidref_set_pid(&pidref, pid);
|
||||||
|
(void) pidref_wait_for_terminate(&pidref, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3167,7 +3167,7 @@ int bus_exec_context_set_transient_property(
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
c->cpu_sched_policy = q;
|
c->cpu_sched_policy = q;
|
||||||
c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(q), sched_get_priority_max(q));
|
c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min_safe(q), sched_get_priority_max_safe(q));
|
||||||
c->cpu_sched_set = true;
|
c->cpu_sched_set = true;
|
||||||
|
|
||||||
unit_write_settingf(u, flags, name, "CPUSchedulingPolicy=%s", s);
|
unit_write_settingf(u, flags, name, "CPUSchedulingPolicy=%s", s);
|
||||||
|
|||||||
@ -2406,7 +2406,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi
|
|||||||
_cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
|
_cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
|
||||||
_cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR;
|
||||||
_cleanup_close_ int unshare_ready_fd = -EBADF;
|
_cleanup_close_ int unshare_ready_fd = -EBADF;
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
uint64_t c = 1;
|
uint64_t c = 1;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
int r;
|
int r;
|
||||||
@ -2503,7 +2503,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi
|
|||||||
if (pipe2(errno_pipe, O_CLOEXEC) < 0)
|
if (pipe2(errno_pipe, O_CLOEXEC) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid);
|
r = pidref_safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -2535,9 +2535,10 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi
|
|||||||
if (n != 0) /* on success we should have read 0 bytes */
|
if (n != 0) /* on success we should have read 0 bytes */
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
r = wait_for_terminate_and_check("(sd-userns)", TAKE_PID(pid), 0);
|
r = pidref_wait_for_terminate_and_check("(sd-userns)", &pidref, 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
pidref_done(&pidref);
|
||||||
if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */
|
if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
@ -2546,7 +2547,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi
|
|||||||
|
|
||||||
static int can_mount_proc(void) {
|
static int can_mount_proc(void) {
|
||||||
_cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -2561,8 +2562,10 @@ static int can_mount_proc(void) {
|
|||||||
|
|
||||||
/* Fork a child process into its own mount and PID namespace. Note safe_fork() already remounts / as SLAVE
|
/* Fork a child process into its own mount and PID namespace. Note safe_fork() already remounts / as SLAVE
|
||||||
* with FORK_MOUNTNS_SLAVE. */
|
* with FORK_MOUNTNS_SLAVE. */
|
||||||
r = safe_fork("(sd-proc-check)",
|
r = pidref_safe_fork(
|
||||||
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_PIDNS, &pid);
|
"(sd-proc-check)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_PIDNS,
|
||||||
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to fork child process (sd-proc-check): %m");
|
return log_debug_errno(r, "Failed to fork child process (sd-proc-check): %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -2597,9 +2600,10 @@ static int can_mount_proc(void) {
|
|||||||
if (n != 0) /* on success we should have read 0 bytes */
|
if (n != 0) /* on success we should have read 0 bytes */
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
r = wait_for_terminate_and_check("(sd-proc-check)", TAKE_PID(pid), /* flags= */ 0);
|
r = pidref_wait_for_terminate_and_check("(sd-proc-check)", &pidref, /* flags= */ 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to wait for (sd-proc-check) child process to terminate: %m");
|
return log_debug_errno(r, "Failed to wait for (sd-proc-check) child process to terminate: %m");
|
||||||
|
pidref_done(&pidref);
|
||||||
if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */
|
if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Child process (sd-proc-check) exited with unexpected exit status '%d'.", r);
|
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Child process (sd-proc-check) exited with unexpected exit status '%d'.", r);
|
||||||
|
|
||||||
@ -5469,8 +5473,15 @@ int exec_invoke(
|
|||||||
|
|
||||||
r = sched_setattr(/* pid= */ 0, &attr, /* flags= */ 0);
|
r = sched_setattr(/* pid= */ 0, &attr, /* flags= */ 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
*exit_status = EXIT_SETSCHEDULER;
|
if (errno != EINVAL || sched_policy_supported(attr.sched_policy)) {
|
||||||
return log_error_errno(errno, "Failed to set up CPU scheduling: %m");
|
*exit_status = EXIT_SETSCHEDULER;
|
||||||
|
return log_error_errno(errno, "Failed to set up CPU scheduling: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
_cleanup_free_ char *s = NULL;
|
||||||
|
(void) sched_policy_to_string_alloc(context->cpu_sched_policy, &s);
|
||||||
|
|
||||||
|
log_warning_errno(errno, "CPU scheduling policy %s is not supported, proceeding without.", strna(s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1539,9 +1539,12 @@ int config_parse_exec_cpu_sched_policy(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sched_policy_supported(x))
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, x, "Unsupported CPU scheduling policy: %s", rvalue);
|
||||||
|
|
||||||
c->cpu_sched_policy = x;
|
c->cpu_sched_policy = x;
|
||||||
/* Moving to or from real-time policy? We need to adjust the priority */
|
/* Moving to or from real-time policy? We need to adjust the priority */
|
||||||
c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
|
c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min_safe(x), sched_get_priority_max_safe(x));
|
||||||
c->cpu_sched_set = true;
|
c->cpu_sched_set = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -1557,9 +1557,7 @@ static int socket_address_listen_in_cgroup(
|
|||||||
const SocketAddress *address,
|
const SocketAddress *address,
|
||||||
const char *label) {
|
const char *label) {
|
||||||
|
|
||||||
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
int r;
|
||||||
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
|
|
||||||
int fd, r;
|
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
assert(address);
|
assert(address);
|
||||||
@ -1571,11 +1569,11 @@ static int socket_address_listen_in_cgroup(
|
|||||||
|
|
||||||
if (!fork_needed(address, s)) {
|
if (!fork_needed(address, s)) {
|
||||||
/* Shortcut things... */
|
/* Shortcut things... */
|
||||||
fd = socket_address_listen_do(s, address, label);
|
r = socket_address_listen_do(s, address, label);
|
||||||
if (fd < 0)
|
if (r < 0)
|
||||||
return log_address_error_errno(UNIT(s), address, fd, "Failed to create listening socket (%s): %m");
|
return log_address_error_errno(UNIT(s), address, r, "Failed to create listening socket (%s): %m");
|
||||||
|
|
||||||
return fd;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = unit_setup_exec_runtime(UNIT(s));
|
r = unit_setup_exec_runtime(UNIT(s));
|
||||||
@ -1605,6 +1603,10 @@ static int socket_address_listen_in_cgroup(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
||||||
|
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
|
||||||
|
_cleanup_close_ int fd = -EBADF;
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
|
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
|
||||||
return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m");
|
return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m");
|
||||||
|
|
||||||
@ -1653,16 +1655,14 @@ static int socket_address_listen_in_cgroup(
|
|||||||
fd = receive_one_fd(pair[0], 0);
|
fd = receive_one_fd(pair[0], 0);
|
||||||
|
|
||||||
/* We synchronously wait for the helper, as it shouldn't be slow */
|
/* We synchronously wait for the helper, as it shouldn't be slow */
|
||||||
r = wait_for_terminate_and_check("(sd-listen)", pid.pid, WAIT_LOG_ABNORMAL);
|
r = pidref_wait_for_terminate_and_check("(sd-listen)", &pid, WAIT_LOG_ABNORMAL);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
safe_close(fd);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_address_error_errno(UNIT(s), address, fd, "Failed to receive listening socket (%s): %m");
|
return log_address_error_errno(UNIT(s), address, fd, "Failed to receive listening socket (%s): %m");
|
||||||
|
|
||||||
return fd;
|
return TAKE_FD(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_open_fds(Socket *orig_s) {
|
static int socket_open_fds(Socket *orig_s) {
|
||||||
@ -3181,7 +3181,7 @@ static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) {
|
|||||||
cfd = receive_one_fd(pair[0], 0);
|
cfd = receive_one_fd(pair[0], 0);
|
||||||
|
|
||||||
/* We synchronously wait for the helper, as it shouldn't be slow */
|
/* We synchronously wait for the helper, as it shouldn't be slow */
|
||||||
r = wait_for_terminate_and_check("(sd-accept)", pid.pid, WAIT_LOG_ABNORMAL);
|
r = pidref_wait_for_terminate_and_check("(sd-accept)", &pid, WAIT_LOG_ABNORMAL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
safe_close(cfd);
|
safe_close(cfd);
|
||||||
return r;
|
return r;
|
||||||
@ -3189,7 +3189,7 @@ static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) {
|
|||||||
|
|
||||||
/* If we received no fd, we got EIO here. If this happens with a process exit code of EXIT_SUCCESS
|
/* If we received no fd, we got EIO here. If this happens with a process exit code of EXIT_SUCCESS
|
||||||
* this is a spurious accept(), let's convert that back to EAGAIN here. */
|
* this is a spurious accept(), let's convert that back to EAGAIN here. */
|
||||||
if (cfd == -EIO)
|
if (cfd == -EIO && r == EXIT_SUCCESS)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
if (cfd < 0)
|
if (cfd < 0)
|
||||||
return log_unit_error_errno(UNIT(s), cfd, "Failed to receive connection socket: %m");
|
return log_unit_error_errno(UNIT(s), cfd, "Failed to receive connection socket: %m");
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
#include "parse-argument.h"
|
#include "parse-argument.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
@ -1177,7 +1178,6 @@ static int run_debug(int argc, char **argv, void *userdata) {
|
|||||||
bool unlink_path = false;
|
bool unlink_path = false;
|
||||||
const char *data, *fork_name;
|
const char *data, *fork_name;
|
||||||
size_t len;
|
size_t len;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!arg_debugger) {
|
if (!arg_debugger) {
|
||||||
@ -1271,7 +1271,11 @@ static int run_debug(int argc, char **argv, void *userdata) {
|
|||||||
|
|
||||||
fork_name = strjoina("(", debugger_call[0], ")");
|
fork_name = strjoina("(", debugger_call[0], ")");
|
||||||
|
|
||||||
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork(
|
||||||
|
fork_name,
|
||||||
|
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO,
|
||||||
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -1281,7 +1285,7 @@ static int run_debug(int argc, char **argv, void *userdata) {
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wait_for_terminate_and_check(debugger_call[0], pid, WAIT_LOG_ABNORMAL);
|
r = pidref_wait_for_terminate_and_check(debugger_call[0], &pidref, WAIT_LOG_ABNORMAL);
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
(void) default_signals(SIGINT, SIGTERM);
|
(void) default_signals(SIGINT, SIGTERM);
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
#include "parse-argument.h"
|
#include "parse-argument.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
@ -140,7 +141,6 @@ static int notify_override_unchanged(const char *f) {
|
|||||||
|
|
||||||
static int found_override(const char *top, const char *bottom) {
|
static int found_override(const char *top, const char *bottom) {
|
||||||
_cleanup_free_ char *dest = NULL;
|
_cleanup_free_ char *dest = NULL;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(top);
|
assert(top);
|
||||||
@ -165,7 +165,11 @@ static int found_override(const char *top, const char *bottom) {
|
|||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork(
|
||||||
|
"(diff)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG,
|
||||||
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -175,7 +179,7 @@ static int found_override(const char *top, const char *bottom) {
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) wait_for_terminate_and_check("diff", pid, WAIT_LOG_ABNORMAL);
|
(void) pidref_wait_for_terminate_and_check("diff", &pidref, WAIT_LOG_ABNORMAL);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "fsck-util.h"
|
#include "fsck-util.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
@ -267,7 +268,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
bool root_directory;
|
bool root_directory;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int r, exit_status;
|
int r, exit_status;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
log_setup();
|
log_setup();
|
||||||
|
|
||||||
@ -366,7 +366,11 @@ static int run(int argc, char *argv[]) {
|
|||||||
pipe(progress_pipe) < 0)
|
pipe(progress_pipe) < 0)
|
||||||
return log_error_errno(errno, "pipe(): %m");
|
return log_error_errno(errno, "pipe(): %m");
|
||||||
|
|
||||||
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork(
|
||||||
|
"(fsck)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
||||||
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -424,7 +428,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
(void) process_progress(TAKE_FD(progress_pipe[0]), console);
|
(void) process_progress(TAKE_FD(progress_pipe[0]), console);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL);
|
exit_status = pidref_wait_for_terminate_and_check("fsck", &pidref, WAIT_LOG_ABNORMAL);
|
||||||
if (exit_status < 0)
|
if (exit_status < 0)
|
||||||
return exit_status;
|
return exit_status;
|
||||||
if ((exit_status & ~FSCK_ERROR_CORRECTED) != FSCK_SUCCESS) {
|
if ((exit_status & ~FSCK_ERROR_CORRECTED) != FSCK_SUCCESS) {
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
#include "password-quality-util.h"
|
#include "password-quality-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "percent-util.h"
|
#include "percent-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "pkcs11-util.h"
|
#include "pkcs11-util.h"
|
||||||
#include "polkit-agent.h"
|
#include "polkit-agent.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
@ -2341,7 +2342,6 @@ static int with_home(int argc, char *argv[], void *userdata) {
|
|||||||
_cleanup_strv_free_ char **cmdline = NULL;
|
_cleanup_strv_free_ char **cmdline = NULL;
|
||||||
const char *home;
|
const char *home;
|
||||||
int r, ret;
|
int r, ret;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
r = acquire_bus(&bus);
|
r = acquire_bus(&bus);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -2414,7 +2414,11 @@ static int with_home(int argc, char *argv[], void *userdata) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_log_parse_error(r);
|
return bus_log_parse_error(r);
|
||||||
|
|
||||||
r = safe_fork("(with)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REOPEN_LOG, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork(
|
||||||
|
"(with)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REOPEN_LOG,
|
||||||
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -2428,7 +2432,7 @@ static int with_home(int argc, char *argv[], void *userdata) {
|
|||||||
_exit(255);
|
_exit(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL);
|
ret = pidref_wait_for_terminate_and_check(cmdline[0], &pidref, WAIT_LOG_ABNORMAL);
|
||||||
|
|
||||||
/* Close the fd that pings the home now. */
|
/* Close the fd that pings the home now. */
|
||||||
acquired_fd = safe_close(acquired_fd);
|
acquired_fd = safe_close(acquired_fd);
|
||||||
|
|||||||
@ -3299,11 +3299,14 @@ int home_wait_for_worker(Home *h) {
|
|||||||
|
|
||||||
log_info("Worker process for home %s is still running while exiting. Waiting for it to finish.", h->user_name);
|
log_info("Worker process for home %s is still running while exiting. Waiting for it to finish.", h->user_name);
|
||||||
|
|
||||||
r = wait_for_terminate_with_timeout(h->worker_pid.pid, 30 * USEC_PER_SEC);
|
siginfo_t si;
|
||||||
|
r = pidref_wait_for_terminate_full(&h->worker_pid, 30 * USEC_PER_SEC, &si);
|
||||||
if (r == -ETIMEDOUT)
|
if (r == -ETIMEDOUT)
|
||||||
log_warning_errno(r, "Waiting for worker process for home %s timed out. Ignoring.", h->user_name);
|
log_warning_errno(r, "Waiting for worker process for home %s timed out. Ignoring.", h->user_name);
|
||||||
else if (r < 0)
|
else if (r < 0)
|
||||||
log_warning_errno(r, "Failed to wait for worker process for home %s. Ignoring.", h->user_name);
|
log_warning_errno(r, "Failed to wait for worker process for home %s, ignoring: %m", h->user_name);
|
||||||
|
else if (si.si_code != CLD_EXITED || si.si_status != 0)
|
||||||
|
log_warning("Worker process for home %s failed with non-zero exit status. Ignoring.", h->user_name);
|
||||||
|
|
||||||
(void) hashmap_remove_value(h->manager->homes_by_worker_pid, &h->worker_pid, h);
|
(void) hashmap_remove_value(h->manager->homes_by_worker_pid, &h->worker_pid, h);
|
||||||
pidref_done(&h->worker_pid);
|
pidref_done(&h->worker_pid);
|
||||||
|
|||||||
@ -1157,7 +1157,7 @@ static int manager_listen_notify(Manager *m) {
|
|||||||
|
|
||||||
r = notify_socket_prepare_full(
|
r = notify_socket_prepare_full(
|
||||||
m->event,
|
m->event,
|
||||||
SD_EVENT_PRIORITY_NORMAL - 5, /* Make sure we process sd_notify() before SIGCHLD for
|
SD_EVENT_PRIORITY_NORMAL - 5, /* Make sure we process sd_notify() before child exit for
|
||||||
* any worker, so that we always know the error number
|
* any worker, so that we always know the error number
|
||||||
* of a client before it exits. */
|
* of a client before it exits. */
|
||||||
on_notify_socket,
|
on_notify_socket,
|
||||||
|
|||||||
@ -12,7 +12,6 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "service-util.h"
|
#include "service-util.h"
|
||||||
#include "signal-util.h"
|
|
||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
_cleanup_(manager_freep) Manager *m = NULL;
|
_cleanup_(manager_freep) Manager *m = NULL;
|
||||||
@ -32,8 +31,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
umask(0022);
|
umask(0022);
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, /* ret_old_mask= */ NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Could not create manager: %m");
|
return log_error_errno(r, "Could not create manager: %m");
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
#include "memfd-util.h"
|
#include "memfd-util.h"
|
||||||
#include "mount-util.h"
|
#include "mount-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -75,14 +76,17 @@ int home_setup_cifs(
|
|||||||
|
|
||||||
STRV_FOREACH(pw, h->password) {
|
STRV_FOREACH(pw, h->password) {
|
||||||
_cleanup_close_ int passwd_fd = -EBADF;
|
_cleanup_close_ int passwd_fd = -EBADF;
|
||||||
pid_t mount_pid;
|
|
||||||
int exit_status;
|
int exit_status;
|
||||||
|
|
||||||
passwd_fd = memfd_new_and_seal_string("cifspw", *pw);
|
passwd_fd = memfd_new_and_seal_string("cifspw", *pw);
|
||||||
if (passwd_fd < 0)
|
if (passwd_fd < 0)
|
||||||
return log_error_errno(passwd_fd, "Failed to create data FD for password: %m");
|
return log_error_errno(passwd_fd, "Failed to create data FD for password: %m");
|
||||||
|
|
||||||
r = safe_fork("(mount)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR, &mount_pid);
|
_cleanup_(pidref_done) PidRef mount_pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork(
|
||||||
|
"(mount)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR,
|
||||||
|
&mount_pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -108,7 +112,7 @@ int home_setup_cifs(
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_status = wait_for_terminate_and_check("mount", mount_pid, WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS);
|
exit_status = pidref_wait_for_terminate_and_check("mount", &mount_pidref, WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS);
|
||||||
if (exit_status < 0)
|
if (exit_status < 0)
|
||||||
return exit_status;
|
return exit_status;
|
||||||
if (exit_status == EXIT_SUCCESS) {
|
if (exit_status == EXIT_SUCCESS) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/xattr.h>
|
#include <sys/xattr.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include "pidref.h"
|
||||||
#if HAVE_VALGRIND_MEMCHECK_H
|
#if HAVE_VALGRIND_MEMCHECK_H
|
||||||
#include <valgrind/memcheck.h>
|
#include <valgrind/memcheck.h>
|
||||||
#endif
|
#endif
|
||||||
@ -227,7 +228,6 @@ static int block_get_size_by_path(const char *path, uint64_t *ret) {
|
|||||||
|
|
||||||
static int run_fsck(const char *node, const char *fstype) {
|
static int run_fsck(const char *node, const char *fstype) {
|
||||||
int r, exit_status;
|
int r, exit_status;
|
||||||
pid_t fsck_pid;
|
|
||||||
|
|
||||||
assert(node);
|
assert(node);
|
||||||
assert(fstype);
|
assert(fstype);
|
||||||
@ -240,9 +240,11 @@ static int run_fsck(const char *node, const char *fstype) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork("(fsck)",
|
_cleanup_(pidref_done) PidRef fsck_pidref = PIDREF_NULL;
|
||||||
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
|
r = pidref_safe_fork(
|
||||||
&fsck_pid);
|
"(fsck)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
|
||||||
|
&fsck_pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -253,7 +255,7 @@ static int run_fsck(const char *node, const char *fstype) {
|
|||||||
_exit(FSCK_OPERATIONAL_ERROR);
|
_exit(FSCK_OPERATIONAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_status = wait_for_terminate_and_check("fsck", fsck_pid, WAIT_LOG_ABNORMAL);
|
exit_status = pidref_wait_for_terminate_and_check("fsck", &fsck_pidref, WAIT_LOG_ABNORMAL);
|
||||||
if (exit_status < 0)
|
if (exit_status < 0)
|
||||||
return exit_status;
|
return exit_status;
|
||||||
if ((exit_status & ~FSCK_ERROR_CORRECTED) != 0) {
|
if ((exit_status & ~FSCK_ERROR_CORRECTED) != 0) {
|
||||||
@ -2604,7 +2606,7 @@ static int ext4_offline_resize_fs(
|
|||||||
|
|
||||||
_cleanup_free_ char *size_str = NULL;
|
_cleanup_free_ char *size_str = NULL;
|
||||||
bool re_open = false, re_mount = false;
|
bool re_open = false, re_mount = false;
|
||||||
pid_t resize_pid, fsck_pid;
|
_cleanup_(pidref_done) PidRef resize_pidref = PIDREF_NULL, fsck_pidref = PIDREF_NULL;
|
||||||
int r, exit_status;
|
int r, exit_status;
|
||||||
|
|
||||||
assert(setup);
|
assert(setup);
|
||||||
@ -2627,9 +2629,10 @@ static int ext4_offline_resize_fs(
|
|||||||
log_info("Temporary unmounting of file system completed.");
|
log_info("Temporary unmounting of file system completed.");
|
||||||
|
|
||||||
/* resize2fs requires that the file system is force checked first, do so. */
|
/* resize2fs requires that the file system is force checked first, do so. */
|
||||||
r = safe_fork("(e2fsck)",
|
r = pidref_safe_fork(
|
||||||
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
|
"(e2fsck)",
|
||||||
&fsck_pid);
|
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
|
||||||
|
&fsck_pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -2640,7 +2643,7 @@ static int ext4_offline_resize_fs(
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_status = wait_for_terminate_and_check("e2fsck", fsck_pid, WAIT_LOG_ABNORMAL);
|
exit_status = pidref_wait_for_terminate_and_check("e2fsck", &fsck_pidref, WAIT_LOG_ABNORMAL);
|
||||||
if (exit_status < 0)
|
if (exit_status < 0)
|
||||||
return exit_status;
|
return exit_status;
|
||||||
if ((exit_status & ~FSCK_ERROR_CORRECTED) != 0) {
|
if ((exit_status & ~FSCK_ERROR_CORRECTED) != 0) {
|
||||||
@ -2659,9 +2662,10 @@ static int ext4_offline_resize_fs(
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
/* Resize the thing */
|
/* Resize the thing */
|
||||||
r = safe_fork("(e2resize)",
|
r = pidref_safe_fork(
|
||||||
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
|
"(e2resize)",
|
||||||
&resize_pid);
|
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
|
||||||
|
&resize_pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
|
|||||||
@ -409,7 +409,7 @@ static int transfer_on_log(sd_event_source *s, int fd, uint32_t revents, void *u
|
|||||||
log_error_errno(errno, "Failed to read log message: %m");
|
log_error_errno(errno, "Failed to read log message: %m");
|
||||||
if (l <= 0) {
|
if (l <= 0) {
|
||||||
/* EOF/read error. We just close the pipe here, and
|
/* EOF/read error. We just close the pipe here, and
|
||||||
* close the watch, waiting for the SIGCHLD to arrive,
|
* close the watch, waiting for the child to exit,
|
||||||
* before we do anything else. */
|
* before we do anything else. */
|
||||||
t->log_event_source = sd_event_source_unref(t->log_event_source);
|
t->log_event_source = sd_event_source_unref(t->log_event_source);
|
||||||
return 0;
|
return 0;
|
||||||
@ -600,7 +600,7 @@ static int transfer_start(Transfer *t) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Make sure always process logging before SIGCHLD */
|
/* Make sure always process logging before child exit */
|
||||||
r = sd_event_source_set_priority(t->log_event_source, SD_EVENT_PRIORITY_NORMAL -5);
|
r = sd_event_source_set_priority(t->log_event_source, SD_EVENT_PRIORITY_NORMAL -5);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -724,7 +724,7 @@ static int manager_new(RuntimeScope scope, Manager **ret) {
|
|||||||
|
|
||||||
r = notify_socket_prepare(
|
r = notify_socket_prepare(
|
||||||
m->event,
|
m->event,
|
||||||
SD_EVENT_PRIORITY_NORMAL - 1, /* Make this processed before SIGCHLD. */
|
SD_EVENT_PRIORITY_NORMAL - 1, /* Make this processed before child exit. */
|
||||||
manager_on_notify,
|
manager_on_notify,
|
||||||
m,
|
m,
|
||||||
&m->notify_socket_path);
|
&m->notify_socket_path);
|
||||||
@ -2062,8 +2062,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
umask(0022);
|
umask(0022);
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(scope, &m);
|
r = manager_new(scope, &m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate manager object: %m");
|
return log_error_errno(r, "Failed to allocate manager object: %m");
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
#include "os-util.h"
|
#include "os-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "pull-common.h"
|
#include "pull-common.h"
|
||||||
#include "pull-job.h"
|
#include "pull-job.h"
|
||||||
@ -404,7 +405,7 @@ static int verify_gpg(
|
|||||||
_cleanup_close_pair_ int gpg_pipe[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int gpg_pipe[2] = EBADF_PAIR;
|
||||||
_cleanup_(rm_rf_physical_and_freep) char *gpg_home = NULL;
|
_cleanup_(rm_rf_physical_and_freep) char *gpg_home = NULL;
|
||||||
char sig_file_path[] = "/tmp/sigXXXXXX";
|
char sig_file_path[] = "/tmp/sigXXXXXX";
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(iovec_is_valid(payload));
|
assert(iovec_is_valid(payload));
|
||||||
@ -434,11 +435,12 @@ static int verify_gpg(
|
|||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork_full("(gpg)",
|
r = pidref_safe_fork_full(
|
||||||
(int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO },
|
"(gpg)",
|
||||||
NULL, 0,
|
(int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO },
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
/* except_fds= */ NULL, /* n_except_fds= */ 0,
|
||||||
&pid);
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
||||||
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -497,9 +499,10 @@ static int verify_gpg(
|
|||||||
|
|
||||||
gpg_pipe[1] = safe_close(gpg_pipe[1]);
|
gpg_pipe[1] = safe_close(gpg_pipe[1]);
|
||||||
|
|
||||||
r = wait_for_terminate_and_check("gpg", TAKE_PID(pid), WAIT_LOG_ABNORMAL);
|
r = pidref_wait_for_terminate_and_check("gpg", &pidref, WAIT_LOG_ABNORMAL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
pidref_done(&pidref);
|
||||||
if (r != EXIT_SUCCESS)
|
if (r != EXIT_SUCCESS)
|
||||||
r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
|
r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||||
"DOWNLOAD INVALID: Signature verification failed.");
|
"DOWNLOAD INVALID: Signature verification failed.");
|
||||||
|
|||||||
@ -55,3 +55,11 @@ int __clone2(int (*fn)(void *), void *stack_base, size_t stack_size, int flags,
|
|||||||
int missing_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned flags);
|
int missing_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned flags);
|
||||||
# define sched_setattr missing_sched_setattr
|
# define sched_setattr missing_sched_setattr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* f0e1a0643a59bf1f922fa209cec86a170b784f3f (6.12),
|
||||||
|
* defined in sched.h in glibc since glibc-2.41. */
|
||||||
|
#ifndef SCHED_EXT
|
||||||
|
# define SCHED_EXT 7
|
||||||
|
#else
|
||||||
|
static_assert(SCHED_EXT == 7, "");
|
||||||
|
#endif
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "bus-match.h"
|
#include "bus-match.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "runtime-scope.h"
|
#include "runtime-scope.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
|
|
||||||
@ -271,7 +272,7 @@ typedef struct sd_bus {
|
|||||||
unsigned n_memfd_cache;
|
unsigned n_memfd_cache;
|
||||||
|
|
||||||
uint64_t origin_id;
|
uint64_t origin_id;
|
||||||
pid_t busexec_pid;
|
PidRef busexec_pidref;
|
||||||
|
|
||||||
unsigned iteration_counter;
|
unsigned iteration_counter;
|
||||||
|
|
||||||
|
|||||||
@ -1163,7 +1163,7 @@ int bus_socket_exec(sd_bus *b) {
|
|||||||
assert(b->input_fd < 0);
|
assert(b->input_fd < 0);
|
||||||
assert(b->output_fd < 0);
|
assert(b->output_fd < 0);
|
||||||
assert(b->exec_path);
|
assert(b->exec_path);
|
||||||
assert(b->busexec_pid == 0);
|
assert(!pidref_is_set(&b->busexec_pidref));
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
if (DEBUG_LOGGING) {
|
||||||
_cleanup_free_ char *line = NULL;
|
_cleanup_free_ char *line = NULL;
|
||||||
@ -1181,10 +1181,12 @@ int bus_socket_exec(sd_bus *b) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = safe_fork_full("(sd-busexec)",
|
r = pidref_safe_fork_full(
|
||||||
(int[]) { s[1], s[1], STDERR_FILENO },
|
"(sd-busexec)",
|
||||||
NULL, 0,
|
(int[]) { s[1], s[1], STDERR_FILENO },
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid);
|
NULL, 0,
|
||||||
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_RLIMIT_NOFILE_SAFE,
|
||||||
|
&b->busexec_pidref);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
safe_close_pair(s);
|
safe_close_pair(s);
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -41,7 +41,6 @@
|
|||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "prioq.h"
|
#include "prioq.h"
|
||||||
#include "process-util.h"
|
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
@ -262,6 +261,7 @@ _public_ int sd_bus_new(sd_bus **ret) {
|
|||||||
.creds_mask = SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME,
|
.creds_mask = SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME,
|
||||||
.accept_fd = true,
|
.accept_fd = true,
|
||||||
.origin_id = origin_id_query(),
|
.origin_id = origin_id_query(),
|
||||||
|
.busexec_pidref = PIDREF_NULL,
|
||||||
.n_groups = SIZE_MAX,
|
.n_groups = SIZE_MAX,
|
||||||
.close_on_exit = true,
|
.close_on_exit = true,
|
||||||
.ucred = UCRED_INVALID,
|
.ucred = UCRED_INVALID,
|
||||||
@ -1121,13 +1121,6 @@ static int bus_parse_next_address(sd_bus *b) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bus_kill_exec(sd_bus *bus) {
|
|
||||||
if (!pid_is_valid(bus->busexec_pid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
sigterm_wait(TAKE_PID(bus->busexec_pid));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bus_start_address(sd_bus *b) {
|
static int bus_start_address(sd_bus *b) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1136,7 +1129,7 @@ static int bus_start_address(sd_bus *b) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
bus_close_fds(b);
|
bus_close_fds(b);
|
||||||
|
|
||||||
bus_kill_exec(b);
|
pidref_done_sigterm_wait(&b->busexec_pidref);
|
||||||
|
|
||||||
/* If you provide multiple different bus-addresses, we
|
/* If you provide multiple different bus-addresses, we
|
||||||
* try all of them in order and use the first one that
|
* try all of them in order and use the first one that
|
||||||
@ -1778,7 +1771,7 @@ _public_ void sd_bus_close(sd_bus *bus) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Don't leave ssh hanging around */
|
/* Don't leave ssh hanging around */
|
||||||
bus_kill_exec(bus);
|
pidref_done_sigterm_wait(&bus->busexec_pidref);
|
||||||
|
|
||||||
bus_set_state(bus, BUS_CLOSED);
|
bus_set_state(bus, BUS_CLOSED);
|
||||||
|
|
||||||
@ -1809,7 +1802,7 @@ _public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Have to do this before flush() to prevent hang */
|
/* Have to do this before flush() to prevent hang */
|
||||||
bus_kill_exec(bus);
|
pidref_done_sigterm_wait(&bus->busexec_pidref);
|
||||||
sd_bus_flush(bus);
|
sd_bus_flush(bus);
|
||||||
|
|
||||||
return sd_bus_close_unref(bus);
|
return sd_bus_close_unref(bus);
|
||||||
|
|||||||
@ -1570,6 +1570,33 @@ static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *us
|
|||||||
return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
|
return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int verify_sigchld(int options) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((options & (WSTOPPED|WCONTINUED)) != 0) {
|
||||||
|
/* Caller must block SIGCHLD before using us to watch for WSTOPPED or WCONTINUED. */
|
||||||
|
|
||||||
|
r = signal_is_blocked(SIGCHLD);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't want the Linux autoreaping logic to take effect when we're watching for process exit, so
|
||||||
|
* check if it is enabled. */
|
||||||
|
|
||||||
|
if (options & WEXITED) {
|
||||||
|
r = autoreaping_enabled();
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r > 0)
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
_public_ int sd_event_add_child(
|
_public_ int sd_event_add_child(
|
||||||
sd_event *e,
|
sd_event *e,
|
||||||
sd_event_source **ret,
|
sd_event_source **ret,
|
||||||
@ -1592,18 +1619,11 @@ _public_ int sd_event_add_child(
|
|||||||
if (!callback)
|
if (!callback)
|
||||||
callback = child_exit_callback;
|
callback = child_exit_callback;
|
||||||
|
|
||||||
|
/* As an optimization we only do these checks on the first child event source created. */
|
||||||
if (e->n_online_child_sources == 0) {
|
if (e->n_online_child_sources == 0) {
|
||||||
/* Caller must block SIGCHLD before using us to watch children, even if pidfd is available,
|
r = verify_sigchld(options);
|
||||||
* for compatibility with pre-pidfd and because we don't want the reap the child processes
|
|
||||||
* ourselves, i.e. call waitid(), and don't want Linux' default internal logic for that to
|
|
||||||
* take effect.
|
|
||||||
*
|
|
||||||
* (As an optimization we only do this check on the first child event source created.) */
|
|
||||||
r = signal_is_blocked(SIGCHLD);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = hashmap_ensure_allocated(&e->child_sources, NULL);
|
r = hashmap_ensure_allocated(&e->child_sources, NULL);
|
||||||
@ -1617,8 +1637,8 @@ _public_ int sd_event_add_child(
|
|||||||
if (!s)
|
if (!s)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* We always take a pidfd here if we can, even if we wait for anything else than WEXITED, so that we
|
/* We always take a pidfd here, even if we wait for anything else than WEXITED, so that we pin the
|
||||||
* pin the PID, and make regular waitid() handling race-free. */
|
* PID, and make regular waitid() handling race-free. */
|
||||||
|
|
||||||
s->child.pidfd = pidfd_open(pid, 0);
|
s->child.pidfd = pidfd_open(pid, 0);
|
||||||
if (s->child.pidfd < 0)
|
if (s->child.pidfd < 0)
|
||||||
@ -1685,11 +1705,9 @@ _public_ int sd_event_add_child_pidfd(
|
|||||||
callback = child_exit_callback;
|
callback = child_exit_callback;
|
||||||
|
|
||||||
if (e->n_online_child_sources == 0) {
|
if (e->n_online_child_sources == 0) {
|
||||||
r = signal_is_blocked(SIGCHLD);
|
r = verify_sigchld(options);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = hashmap_ensure_allocated(&e->child_sources, NULL);
|
r = hashmap_ensure_allocated(&e->child_sources, NULL);
|
||||||
|
|||||||
@ -6,12 +6,14 @@
|
|||||||
#include "sd-event.h"
|
#include "sd-event.h"
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "event-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pidfd-util.h"
|
#include "pidfd-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "random-util.h"
|
#include "random-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
@ -91,7 +93,7 @@ static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si,
|
|||||||
|
|
||||||
ASSERT_PTR_EQ(userdata, INT_TO_PTR('e'));
|
ASSERT_PTR_EQ(userdata, INT_TO_PTR('e'));
|
||||||
|
|
||||||
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGUSR2));
|
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR2));
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(pid = fork());
|
ASSERT_OK_ERRNO(pid = fork());
|
||||||
|
|
||||||
@ -566,8 +568,6 @@ TEST(pidfd) {
|
|||||||
int pidfd;
|
int pidfd;
|
||||||
pid_t pid, pid2;
|
pid_t pid, pid2;
|
||||||
|
|
||||||
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
|
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(pid = fork());
|
ASSERT_OK_ERRNO(pid = fork());
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
/* child */
|
/* child */
|
||||||
@ -999,8 +999,6 @@ static int child_handler_wnowait(sd_event_source *s, const siginfo_t *si, void *
|
|||||||
TEST(child_wnowait) {
|
TEST(child_wnowait) {
|
||||||
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
||||||
|
|
||||||
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
|
|
||||||
|
|
||||||
ASSERT_OK(sd_event_default(&e));
|
ASSERT_OK(sd_event_default(&e));
|
||||||
|
|
||||||
/* Fork a subprocess */
|
/* Fork a subprocess */
|
||||||
@ -1032,8 +1030,6 @@ TEST(child_wnowait) {
|
|||||||
TEST(child_pidfd_wnowait) {
|
TEST(child_pidfd_wnowait) {
|
||||||
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
||||||
|
|
||||||
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
|
|
||||||
|
|
||||||
ASSERT_OK(sd_event_default(&e));
|
ASSERT_OK(sd_event_default(&e));
|
||||||
|
|
||||||
/* Fork a subprocess */
|
/* Fork a subprocess */
|
||||||
@ -1167,4 +1163,31 @@ TEST(defer_fair_scheduling) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(child_autoreap_ebusy) {
|
||||||
|
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
||||||
|
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
|
||||||
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
|
|
||||||
|
/* Test that sd_event_add_child() fails with EBUSY when kernel autoreaping is enabled
|
||||||
|
* by setting SIGCHLD disposition to SIG_IGN */
|
||||||
|
|
||||||
|
ASSERT_OK(sd_event_new(&e));
|
||||||
|
|
||||||
|
/* First, verify that adding a child source works with default signal disposition */
|
||||||
|
ASSERT_OK_POSITIVE(pidref_safe_fork("(child-autoreaping-ebusy)", FORK_DEATHSIG_SIGKILL|FORK_FREEZE, &pidref));
|
||||||
|
|
||||||
|
ASSERT_OK(event_add_child_pidref(e, &s, &pidref, WEXITED, NULL, NULL));
|
||||||
|
s = sd_event_source_unref(s);
|
||||||
|
|
||||||
|
/* Now set SIGCHLD to SIG_IGN to enable kernel autoreaping */
|
||||||
|
struct sigaction old_sa, new_sa = {};
|
||||||
|
new_sa.sa_handler = SIG_IGN;
|
||||||
|
ASSERT_OK_ERRNO(sigaction(SIGCHLD, &new_sa, &old_sa));
|
||||||
|
|
||||||
|
ASSERT_ERROR(event_add_child_pidref(e, &s, &pidref, WEXITED, NULL, NULL), EBUSY);
|
||||||
|
|
||||||
|
/* Restore original SIGCHLD disposition */
|
||||||
|
ASSERT_OK_ERRNO(sigaction(SIGCHLD, &old_sa, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pidfd-util.h"
|
#include "pidfd-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
@ -149,6 +150,8 @@ static int varlink_new(sd_varlink **ret) {
|
|||||||
.allow_fd_passing_input = -1,
|
.allow_fd_passing_input = -1,
|
||||||
|
|
||||||
.af = -1,
|
.af = -1,
|
||||||
|
|
||||||
|
.exec_pidref = PIDREF_NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
*ret = v;
|
*ret = v;
|
||||||
@ -209,7 +212,7 @@ _public_ int sd_varlink_connect_address(sd_varlink **ret, const char *address) {
|
|||||||
|
|
||||||
_public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, char **_argv) {
|
_public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, char **_argv) {
|
||||||
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
_cleanup_free_ char *command = NULL;
|
_cleanup_free_ char *command = NULL;
|
||||||
_cleanup_strv_free_ char **argv = NULL;
|
_cleanup_strv_free_ char **argv = NULL;
|
||||||
int r;
|
int r;
|
||||||
@ -239,13 +242,13 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to disable O_NONBLOCK for varlink socket: %m");
|
return log_debug_errno(r, "Failed to disable O_NONBLOCK for varlink socket: %m");
|
||||||
|
|
||||||
r = safe_fork_full(
|
r = pidref_safe_fork_full(
|
||||||
"(sd-vlexec)",
|
"(sd-vlexec)",
|
||||||
/* stdio_fds= */ NULL,
|
/* stdio_fds= */ NULL,
|
||||||
/* except_fds= */ (int[]) { pair[1] },
|
/* except_fds= */ (int[]) { pair[1] },
|
||||||
/* n_except_fds= */ 1,
|
/* n_except_fds= */ 1,
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
||||||
&pid);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -266,7 +269,7 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
xsprintf(spid, PID_FMT, pid);
|
xsprintf(spid, PID_FMT, pidref.pid);
|
||||||
|
|
||||||
uint64_t pidfdid;
|
uint64_t pidfdid;
|
||||||
if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
|
if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
|
||||||
@ -298,7 +301,7 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
|
|||||||
|
|
||||||
v->output_fd = v->input_fd = TAKE_FD(pair[0]);
|
v->output_fd = v->input_fd = TAKE_FD(pair[0]);
|
||||||
v->af = AF_UNIX;
|
v->af = AF_UNIX;
|
||||||
v->exec_pid = TAKE_PID(pid);
|
v->exec_pidref = TAKE_PIDREF(pidref);
|
||||||
varlink_set_state(v, VARLINK_IDLE_CLIENT);
|
varlink_set_state(v, VARLINK_IDLE_CLIENT);
|
||||||
|
|
||||||
*ret = v;
|
*ret = v;
|
||||||
@ -318,7 +321,7 @@ static int ssh_path(const char **ret) {
|
|||||||
|
|
||||||
static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
|
static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
|
||||||
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_return(ret, -EINVAL);
|
assert_return(ret, -EINVAL);
|
||||||
@ -356,13 +359,13 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
|
|||||||
if (socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, pair) < 0)
|
if (socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, pair) < 0)
|
||||||
return log_debug_errno(errno, "Failed to allocate AF_UNIX socket pair: %m");
|
return log_debug_errno(errno, "Failed to allocate AF_UNIX socket pair: %m");
|
||||||
|
|
||||||
r = safe_fork_full(
|
r = pidref_safe_fork_full(
|
||||||
"(sd-vlssh)",
|
"(sd-vlssh)",
|
||||||
/* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO },
|
/* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO },
|
||||||
/* except_fds= */ NULL,
|
/* except_fds= */ NULL,
|
||||||
/* n_except_fds= */ 0,
|
/* n_except_fds= */ 0,
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
||||||
&pid);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -382,7 +385,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
|
|||||||
|
|
||||||
v->output_fd = v->input_fd = TAKE_FD(pair[0]);
|
v->output_fd = v->input_fd = TAKE_FD(pair[0]);
|
||||||
v->af = AF_UNIX;
|
v->af = AF_UNIX;
|
||||||
v->exec_pid = TAKE_PID(pid);
|
v->exec_pidref = TAKE_PIDREF(pidref);
|
||||||
varlink_set_state(v, VARLINK_IDLE_CLIENT);
|
varlink_set_state(v, VARLINK_IDLE_CLIENT);
|
||||||
|
|
||||||
*ret = v;
|
*ret = v;
|
||||||
@ -391,7 +394,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
|
|||||||
|
|
||||||
static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
|
static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
|
||||||
_cleanup_close_pair_ int input_pipe[2] = EBADF_PAIR, output_pipe[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int input_pipe[2] = EBADF_PAIR, output_pipe[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_return(ret, -EINVAL);
|
assert_return(ret, -EINVAL);
|
||||||
@ -440,13 +443,13 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
|
|||||||
if (pipe2(output_pipe, O_CLOEXEC) < 0)
|
if (pipe2(output_pipe, O_CLOEXEC) < 0)
|
||||||
return log_debug_errno(errno, "Failed to allocate output pipe: %m");
|
return log_debug_errno(errno, "Failed to allocate output pipe: %m");
|
||||||
|
|
||||||
r = safe_fork_full(
|
r = pidref_safe_fork_full(
|
||||||
"(sd-vlssh)",
|
"(sd-vlssh)",
|
||||||
/* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO },
|
/* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO },
|
||||||
/* except_fds= */ NULL,
|
/* except_fds= */ NULL,
|
||||||
/* n_except_fds= */ 0,
|
/* n_except_fds= */ 0,
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
|
||||||
&pid);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to spawn process: %m");
|
return log_debug_errno(r, "Failed to spawn process: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -475,7 +478,7 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
|
|||||||
v->input_fd = TAKE_FD(output_pipe[0]);
|
v->input_fd = TAKE_FD(output_pipe[0]);
|
||||||
v->output_fd = TAKE_FD(input_pipe[1]);
|
v->output_fd = TAKE_FD(input_pipe[1]);
|
||||||
v->af = AF_UNSPEC;
|
v->af = AF_UNSPEC;
|
||||||
v->exec_pid = TAKE_PID(pid);
|
v->exec_pidref = TAKE_PIDREF(pidref);
|
||||||
varlink_set_state(v, VARLINK_IDLE_CLIENT);
|
varlink_set_state(v, VARLINK_IDLE_CLIENT);
|
||||||
|
|
||||||
*ret = v;
|
*ret = v;
|
||||||
@ -648,10 +651,7 @@ static void varlink_clear(sd_varlink *v) {
|
|||||||
|
|
||||||
v->event = sd_event_unref(v->event);
|
v->event = sd_event_unref(v->event);
|
||||||
|
|
||||||
if (v->exec_pid > 0) {
|
pidref_done_sigterm_wait(&v->exec_pidref);
|
||||||
sigterm_wait(v->exec_pid);
|
|
||||||
v->exec_pid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
v->peer_pidfd = safe_close(v->peer_pidfd);
|
v->peer_pidfd = safe_close(v->peer_pidfd);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "sd-varlink.h"
|
#include "sd-varlink.h"
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "sd-forward.h"
|
#include "sd-forward.h"
|
||||||
|
|
||||||
typedef enum VarlinkState {
|
typedef enum VarlinkState {
|
||||||
@ -187,7 +188,7 @@ struct sd_varlink {
|
|||||||
sd_event_source *quit_event_source;
|
sd_event_source *quit_event_source;
|
||||||
sd_event_source *defer_event_source;
|
sd_event_source *defer_event_source;
|
||||||
|
|
||||||
pid_t exec_pid;
|
PidRef exec_pidref;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct VarlinkServerSocket VarlinkServerSocket;
|
typedef struct VarlinkServerSocket VarlinkServerSocket;
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
#include "parse-argument.h"
|
#include "parse-argument.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "polkit-agent.h"
|
#include "polkit-agent.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
@ -330,7 +331,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
_cleanup_strv_free_ char **arguments = NULL;
|
_cleanup_strv_free_ char **arguments = NULL;
|
||||||
_cleanup_free_ char *w = NULL;
|
_cleanup_free_ char *w = NULL;
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
/* Ignore SIGINT and allow the forked process to receive it */
|
/* Ignore SIGINT and allow the forked process to receive it */
|
||||||
(void) ignore_signals(SIGINT);
|
(void) ignore_signals(SIGINT);
|
||||||
@ -360,7 +360,8 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (!arguments)
|
if (!arguments)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -371,7 +372,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wait_for_terminate_and_check(argv[optind], pid, WAIT_LOG);
|
return pidref_wait_for_terminate_and_check(argv[optind], &pidref, WAIT_LOG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1372,8 +1372,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
(void) mkdir_label("/run/systemd/users", 0755);
|
(void) mkdir_label("/run/systemd/users", 0755);
|
||||||
(void) mkdir_label("/run/systemd/sessions", 0755);
|
(void) mkdir_label("/run/systemd/sessions", 0755);
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, /* ret_old_mask= */ NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate manager object: %m");
|
return log_error_errno(r, "Failed to allocate manager object: %m");
|
||||||
|
|||||||
@ -32,7 +32,7 @@ int bus_image_method_remove(
|
|||||||
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
||||||
Image *image = ASSERT_PTR(userdata);
|
Image *image = ASSERT_PTR(userdata);
|
||||||
Manager *m = image->userdata;
|
Manager *m = image->userdata;
|
||||||
pid_t child;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
@ -62,7 +62,7 @@ int bus_image_method_remove(
|
|||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
||||||
|
|
||||||
r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
|
r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -73,11 +73,11 @@ int bus_image_method_remove(
|
|||||||
|
|
||||||
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
||||||
|
|
||||||
r = operation_new_with_bus_reply(m, /* machine= */ NULL, child, message, errno_pipe_fd[0], /* ret= */ NULL);
|
r = operation_new_with_bus_reply(m, /* machine= */ NULL, &child, message, errno_pipe_fd[0], /* ret= */ NULL);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
sigkill_wait(child);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
TAKE_PIDREF(child);
|
||||||
|
|
||||||
errno_pipe_fd[0] = -EBADF;
|
errno_pipe_fd[0] = -EBADF;
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ int bus_image_method_clone(
|
|||||||
Manager *m = ASSERT_PTR(image->userdata);
|
Manager *m = ASSERT_PTR(image->userdata);
|
||||||
const char *new_name;
|
const char *new_name;
|
||||||
int r, read_only;
|
int r, read_only;
|
||||||
pid_t child;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ int bus_image_method_clone(
|
|||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
||||||
|
|
||||||
r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
|
r = pidref_safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -188,11 +188,11 @@ int bus_image_method_clone(
|
|||||||
|
|
||||||
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
||||||
|
|
||||||
r = operation_new_with_bus_reply(m, /* machine= */ NULL, child, message, errno_pipe_fd[0], /* ret= */ NULL);
|
r = operation_new_with_bus_reply(m, /* machine= */ NULL, &child, message, errno_pipe_fd[0], /* ret= */ NULL);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
sigkill_wait(child);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
TAKE_PIDREF(child);
|
||||||
|
|
||||||
errno_pipe_fd[0] = -EBADF;
|
errno_pipe_fd[0] = -EBADF;
|
||||||
|
|
||||||
|
|||||||
@ -115,7 +115,7 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
||||||
ImageUpdateParameters p = IMAGE_UPDATE_PARAMETERS_NULL;
|
ImageUpdateParameters p = IMAGE_UPDATE_PARAMETERS_NULL;
|
||||||
Image *image;
|
Image *image;
|
||||||
pid_t child;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
@ -156,7 +156,7 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return log_debug_errno(errno, "Failed to open pipe: %m");
|
return log_debug_errno(errno, "Failed to open pipe: %m");
|
||||||
|
|
||||||
r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
|
r = pidref_safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to fork: %m");
|
return log_debug_errno(r, "Failed to fork: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -167,12 +167,11 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
|
|
||||||
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
||||||
|
|
||||||
r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, child, link, errno_pipe_fd[0], /* ret= */ NULL);
|
r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, &child, link, errno_pipe_fd[0], /* ret= */ NULL);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
sigkill_wait(child);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
|
TAKE_PIDREF(child);
|
||||||
TAKE_FD(errno_pipe_fd[0]);
|
TAKE_FD(errno_pipe_fd[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -188,7 +187,7 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
|||||||
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
||||||
const char *image_name;
|
const char *image_name;
|
||||||
Image *image;
|
Image *image;
|
||||||
pid_t child;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
@ -225,7 +224,7 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
|||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return log_debug_errno(errno, "Failed to open pipe: %m");
|
return log_debug_errno(errno, "Failed to open pipe: %m");
|
||||||
|
|
||||||
r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
|
r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to fork: %m");
|
return log_debug_errno(r, "Failed to fork: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -236,12 +235,11 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
|||||||
|
|
||||||
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
||||||
|
|
||||||
r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, child, link, errno_pipe_fd[0], /* ret= */ NULL);
|
r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, &child, link, errno_pipe_fd[0], /* ret= */ NULL);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
sigkill_wait(child);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
|
TAKE_PIDREF(child);
|
||||||
TAKE_FD(errno_pipe_fd[0]);
|
TAKE_FD(errno_pipe_fd[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,7 +96,7 @@ int clean_pool_read_next_entry(FILE *file, char **ret_name, uint64_t *ret_usage)
|
|||||||
int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operation **ret_operation) {
|
int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operation **ret_operation) {
|
||||||
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
||||||
_cleanup_close_ int result_fd = -EBADF;
|
_cleanup_close_ int result_fd = -EBADF;
|
||||||
_cleanup_(sigkill_waitp) pid_t child = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(manager);
|
assert(manager);
|
||||||
@ -113,7 +113,7 @@ int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operat
|
|||||||
return log_debug_errno(result_fd, "Failed to open tmpfile: %m");
|
return log_debug_errno(result_fd, "Failed to open tmpfile: %m");
|
||||||
|
|
||||||
/* This might be a slow operation, run it asynchronously in a background process */
|
/* This might be a slow operation, run it asynchronously in a background process */
|
||||||
r = safe_fork("(sd-clean)", FORK_RESET_SIGNALS, &child);
|
r = pidref_safe_fork("(sd-clean)", FORK_RESET_SIGNALS, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to fork(): %m");
|
return log_debug_errno(r, "Failed to fork(): %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -183,13 +183,13 @@ int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operat
|
|||||||
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
||||||
|
|
||||||
/* The clean-up might take a while, hence install a watch on the child and return */
|
/* The clean-up might take a while, hence install a watch on the child and return */
|
||||||
r = operation_new(manager, /* machine= */ NULL, child, errno_pipe_fd[0], ret_operation);
|
r = operation_new(manager, /* machine= */ NULL, &child, errno_pipe_fd[0], ret_operation);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
(*ret_operation)->extra_fd = TAKE_FD(result_fd);
|
(*ret_operation)->extra_fd = TAKE_FD(result_fd);
|
||||||
TAKE_FD(errno_pipe_fd[0]);
|
TAKE_FD(errno_pipe_fd[0]);
|
||||||
TAKE_PID(child);
|
TAKE_PIDREF(child);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1244,7 +1244,7 @@ int machine_copy_from_to_operation(
|
|||||||
|
|
||||||
// TODO: port to PidRef and donate child rather than destroying it
|
// TODO: port to PidRef and donate child rather than destroying it
|
||||||
Operation *operation;
|
Operation *operation;
|
||||||
r = operation_new(manager, machine, child.pid, errno_pipe_fd[0], &operation);
|
r = operation_new(manager, machine, &child, errno_pipe_fd[0], &operation);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -366,8 +366,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (scope == RUNTIME_SCOPE_SYSTEM)
|
if (scope == RUNTIME_SCOPE_SYSTEM)
|
||||||
(void) mkdir_label("/run/systemd/machines", 0755);
|
(void) mkdir_label("/run/systemd/machines", 0755);
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, /* ret_old_mask= */ NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(scope, &m);
|
r = manager_new(scope, &m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate manager object: %m");
|
return log_error_errno(r, "Failed to allocate manager object: %m");
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "sd-varlink.h"
|
#include "sd-varlink.h"
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "event-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -45,10 +46,10 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
|
|||||||
assert(si);
|
assert(si);
|
||||||
|
|
||||||
log_debug("Operation " PID_FMT " is now complete with code=%s status=%i",
|
log_debug("Operation " PID_FMT " is now complete with code=%s status=%i",
|
||||||
o->pid,
|
o->pidref.pid,
|
||||||
sigchld_code_to_string(si->si_code), si->si_status);
|
sigchld_code_to_string(si->si_code), si->si_status);
|
||||||
|
|
||||||
o->pid = 0;
|
pidref_done(&o->pidref);
|
||||||
|
|
||||||
r = read_operation_errno(si, o);
|
r = read_operation_errno(si, o);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -96,12 +97,12 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd, Operation **ret) {
|
int operation_new(Manager *manager, Machine *machine, PidRef *child, int errno_fd, Operation **ret) {
|
||||||
Operation *o;
|
Operation *o;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(manager);
|
assert(manager);
|
||||||
assert(child > 1);
|
assert(pidref_is_set(child));
|
||||||
assert(errno_fd >= 0);
|
assert(errno_fd >= 0);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
@ -110,12 +111,12 @@ int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
*o = (Operation) {
|
*o = (Operation) {
|
||||||
.pid = child,
|
.pidref = TAKE_PIDREF(*child),
|
||||||
.errno_fd = errno_fd,
|
.errno_fd = errno_fd,
|
||||||
.extra_fd = -EBADF
|
.extra_fd = -EBADF
|
||||||
};
|
};
|
||||||
|
|
||||||
r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o);
|
r = event_add_child_pidref(manager->event, &o->event_source, &o->pidref, WEXITED, operation_done, o);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
free(o);
|
free(o);
|
||||||
return r;
|
return r;
|
||||||
@ -130,7 +131,7 @@ int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd,
|
|||||||
o->machine = machine;
|
o->machine = machine;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("Started new operation " PID_FMT ".", child);
|
log_debug("Started new operation " PID_FMT ".", o->pidref.pid);
|
||||||
|
|
||||||
/* At this point we took ownership of both the child and the errno file descriptor! */
|
/* At this point we took ownership of both the child and the errno file descriptor! */
|
||||||
|
|
||||||
@ -147,8 +148,7 @@ Operation *operation_free(Operation *o) {
|
|||||||
safe_close(o->errno_fd);
|
safe_close(o->errno_fd);
|
||||||
safe_close(o->extra_fd);
|
safe_close(o->extra_fd);
|
||||||
|
|
||||||
if (o->pid > 1)
|
pidref_done_sigkill_wait(&o->pidref);
|
||||||
sigkill_wait(o->pid);
|
|
||||||
|
|
||||||
sd_bus_message_unref(o->message);
|
sd_bus_message_unref(o->message);
|
||||||
sd_varlink_unref(o->link);
|
sd_varlink_unref(o->link);
|
||||||
|
|||||||
@ -3,13 +3,14 @@
|
|||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "machine-forward.h"
|
#include "machine-forward.h"
|
||||||
|
#include "pidref.h"
|
||||||
|
|
||||||
#define OPERATIONS_MAX 64
|
#define OPERATIONS_MAX 64
|
||||||
|
|
||||||
typedef struct Operation {
|
typedef struct Operation {
|
||||||
Manager *manager;
|
Manager *manager;
|
||||||
Machine *machine;
|
Machine *machine;
|
||||||
pid_t pid;
|
PidRef pidref;
|
||||||
|
|
||||||
/* only one of these two fields should be set */
|
/* only one of these two fields should be set */
|
||||||
sd_varlink *link;
|
sd_varlink *link;
|
||||||
@ -23,7 +24,7 @@ typedef struct Operation {
|
|||||||
LIST_FIELDS(Operation, operations_by_machine);
|
LIST_FIELDS(Operation, operations_by_machine);
|
||||||
} Operation;
|
} Operation;
|
||||||
|
|
||||||
int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd, Operation **ret);
|
int operation_new(Manager *manager, Machine *machine, PidRef *child, int errno_fd, Operation **ret);
|
||||||
Operation *operation_free(Operation *o);
|
Operation *operation_free(Operation *o);
|
||||||
|
|
||||||
void operation_attach_bus_reply(Operation *op, sd_bus_message *message);
|
void operation_attach_bus_reply(Operation *op, sd_bus_message *message);
|
||||||
@ -32,7 +33,7 @@ void operation_attach_varlink_reply(Operation *op, sd_varlink *link);
|
|||||||
static inline int operation_new_with_bus_reply(
|
static inline int operation_new_with_bus_reply(
|
||||||
Manager *manager,
|
Manager *manager,
|
||||||
Machine *machine,
|
Machine *machine,
|
||||||
pid_t child,
|
PidRef *child,
|
||||||
sd_bus_message *message,
|
sd_bus_message *message,
|
||||||
int errno_fd,
|
int errno_fd,
|
||||||
Operation **ret) {
|
Operation **ret) {
|
||||||
@ -55,7 +56,7 @@ static inline int operation_new_with_bus_reply(
|
|||||||
static inline int operation_new_with_varlink_reply(
|
static inline int operation_new_with_varlink_reply(
|
||||||
Manager *manager,
|
Manager *manager,
|
||||||
Machine *machine,
|
Machine *machine,
|
||||||
pid_t child,
|
PidRef *child,
|
||||||
sd_varlink *link,
|
sd_varlink *link,
|
||||||
int errno_fd,
|
int errno_fd,
|
||||||
Operation **ret) {
|
Operation **ret) {
|
||||||
|
|||||||
@ -51,7 +51,7 @@ static int on_worker_exit(sd_event_source *s, const siginfo_t *si, void *userdat
|
|||||||
else if (si->si_code == CLD_DUMPED)
|
else if (si->si_code == CLD_DUMPED)
|
||||||
log_warning("Worker " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
|
log_warning("Worker " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
|
||||||
else
|
else
|
||||||
log_warning("Got unexpected exit code via SIGCHLD, ignoring.");
|
log_warning("Got unexpected exit code from child, ignoring.");
|
||||||
|
|
||||||
(void) start_workers(m, /* explicit_request= */ false); /* Fill up workers again if we fell below the low watermark */
|
(void) start_workers(m, /* explicit_request= */ false); /* Fill up workers again if we fell below the low watermark */
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "mountfsd-manager.h"
|
#include "mountfsd-manager.h"
|
||||||
#include "signal-util.h"
|
|
||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||||
@ -22,8 +21,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (argc != 1)
|
if (argc != 1)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Could not create manager: %m");
|
return log_error_errno(r, "Could not create manager: %m");
|
||||||
|
|||||||
@ -506,9 +506,10 @@ static int action_fork(char *const *_command) {
|
|||||||
_cleanup_free_ char *addr_string = NULL;
|
_cleanup_free_ char *addr_string = NULL;
|
||||||
r = notify_socket_prepare(
|
r = notify_socket_prepare(
|
||||||
event,
|
event,
|
||||||
SD_EVENT_PRIORITY_NORMAL - 10, /* If we receive both the sd_notify() message and a
|
SD_EVENT_PRIORITY_NORMAL - 10, /* If we receive both the sd_notify() message and
|
||||||
* SIGCHLD always process sd_notify() first, it's the
|
* child exit notification, always process sd_notify()
|
||||||
* more interesting, "positive" information. */
|
* first, it's the more interesting, "positive"
|
||||||
|
* information. */
|
||||||
on_notify_socket,
|
on_notify_socket,
|
||||||
&child,
|
&child,
|
||||||
&addr_string);
|
&addr_string);
|
||||||
@ -541,14 +542,12 @@ static int action_fork(char *const *_command) {
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
|
||||||
|
|
||||||
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *child_event_source = NULL;
|
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *child_event_source = NULL;
|
||||||
r = event_add_child_pidref(event, &child_event_source, &child, WEXITED, on_child, /* userdata= */ NULL);
|
r = event_add_child_pidref(event, &child_event_source, &child, WEXITED, on_child, /* userdata= */ NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate child source: %m");
|
return log_error_errno(r, "Failed to allocate child source: %m");
|
||||||
|
|
||||||
/* Handle SIGCHLD before propagating the other signals below */
|
/* Handle child exit before propagating the other signals below */
|
||||||
r = sd_event_source_set_priority(child_event_source, SD_EVENT_PRIORITY_NORMAL - 5);
|
r = sd_event_source_set_priority(child_event_source, SD_EVENT_PRIORITY_NORMAL - 5);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to change child event source priority: %m");
|
return log_error_errno(r, "Failed to change child event source priority: %m");
|
||||||
|
|||||||
@ -11,26 +11,28 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
#include "nspawn-setuid.h"
|
#include "nspawn-setuid.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
|
|
||||||
static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
|
static int spawn_getent(const char *database, const char *key, PidRef *ret) {
|
||||||
int pipe_fds[2], r;
|
int pipe_fds[2], r;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
assert(database);
|
assert(database);
|
||||||
assert(key);
|
assert(key);
|
||||||
assert(rpid);
|
assert(ret);
|
||||||
|
|
||||||
if (pipe2(pipe_fds, O_CLOEXEC) < 0)
|
if (pipe2(pipe_fds, O_CLOEXEC) < 0)
|
||||||
return log_error_errno(errno, "Failed to allocate pipe: %m");
|
return log_error_errno(errno, "Failed to allocate pipe: %m");
|
||||||
|
|
||||||
r = safe_fork_full("(getent)",
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
(int[]) { -EBADF, pipe_fds[1], -EBADF }, NULL, 0,
|
r = pidref_safe_fork_full(
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
"(getent)",
|
||||||
&pid);
|
(int[]) { -EBADF, pipe_fds[1], -EBADF }, NULL, 0,
|
||||||
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
||||||
|
&pidref);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
safe_close_pair(pipe_fds);
|
safe_close_pair(pipe_fds);
|
||||||
return r;
|
return r;
|
||||||
@ -43,7 +45,7 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
|
|||||||
|
|
||||||
pipe_fds[1] = safe_close(pipe_fds[1]);
|
pipe_fds[1] = safe_close(pipe_fds[1]);
|
||||||
|
|
||||||
*rpid = pid;
|
*ret = TAKE_PIDREF(pidref);
|
||||||
|
|
||||||
return pipe_fds[0];
|
return pipe_fds[0];
|
||||||
}
|
}
|
||||||
@ -84,7 +86,6 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
|
|||||||
unsigned n_gids = 0;
|
unsigned n_gids = 0;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(ret_home);
|
assert(ret_home);
|
||||||
@ -101,7 +102,8 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* First, get user credentials */
|
/* First, get user credentials */
|
||||||
fd = spawn_getent("passwd", user, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
fd = spawn_getent("passwd", user, &pidref);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
@ -116,7 +118,7 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to read from getent: %m");
|
return log_error_errno(r, "Failed to read from getent: %m");
|
||||||
|
|
||||||
(void) wait_for_terminate_and_check("getent passwd", pid, WAIT_LOG);
|
(void) pidref_wait_for_terminate_and_check("getent passwd", &pidref, WAIT_LOG);
|
||||||
|
|
||||||
x = strchr(line, ':');
|
x = strchr(line, ':');
|
||||||
if (!x)
|
if (!x)
|
||||||
@ -173,7 +175,8 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
|
|||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
/* Second, get group memberships */
|
/* Second, get group memberships */
|
||||||
fd = spawn_getent("initgroups", user, &pid);
|
pidref_done(&pidref);
|
||||||
|
fd = spawn_getent("initgroups", user, &pidref);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
@ -188,7 +191,7 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to read from getent: %m");
|
return log_error_errno(r, "Failed to read from getent: %m");
|
||||||
|
|
||||||
(void) wait_for_terminate_and_check("getent initgroups", pid, WAIT_LOG);
|
(void) pidref_wait_for_terminate_and_check("getent initgroups", &pidref, WAIT_LOG);
|
||||||
|
|
||||||
/* Skip over the username and subsequent separator whitespace */
|
/* Skip over the username and subsequent separator whitespace */
|
||||||
x = line;
|
x = line;
|
||||||
|
|||||||
@ -2884,7 +2884,7 @@ static int recursive_chown(const char *directory, uid_t shift, uid_t range) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Return values:
|
* Return values:
|
||||||
* < 0 : wait_for_terminate() failed to get the state of the
|
* < 0 : pidref_wait_for_terminate() failed to get the state of the
|
||||||
* container, the container was terminated by a signal, or
|
* container, the container was terminated by a signal, or
|
||||||
* failed for an unknown reason. No change is made to the
|
* failed for an unknown reason. No change is made to the
|
||||||
* container argument.
|
* container argument.
|
||||||
|
|||||||
@ -58,7 +58,7 @@ static int on_worker_exit(sd_event_source *s, const siginfo_t *si, void *userdat
|
|||||||
else if (si->si_code == CLD_DUMPED)
|
else if (si->si_code == CLD_DUMPED)
|
||||||
log_warning("Worker " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
|
log_warning("Worker " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
|
||||||
else
|
else
|
||||||
log_warning("Got unexpected exit code via SIGCHLD, ignoring.");
|
log_warning("Got unexpected exit code from child, ignoring.");
|
||||||
|
|
||||||
(void) start_workers(m, /* explicit_request= */ false); /* Fill up workers again if we fell below the low watermark */
|
(void) start_workers(m, /* explicit_request= */ false); /* Fill up workers again if we fell below the low watermark */
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "nsresourced-manager.h"
|
#include "nsresourced-manager.h"
|
||||||
#include "signal-util.h"
|
|
||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
_cleanup_(manager_freep) Manager *m = NULL;
|
_cleanup_(manager_freep) Manager *m = NULL;
|
||||||
@ -25,8 +24,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (setenv("SYSTEMD_BYPASS_USERDB", "io.systemd.NamespaceResource", 1) < 0)
|
if (setenv("SYSTEMD_BYPASS_USERDB", "io.systemd.NamespaceResource", 1) < 0)
|
||||||
return log_error_errno(errno, "Failed to set $SYSTEMD_BYPASS_USERDB: %m");
|
return log_error_errno(errno, "Failed to set $SYSTEMD_BYPASS_USERDB: %m");
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Could not create manager: %m");
|
return log_error_errno(r, "Could not create manager: %m");
|
||||||
|
|||||||
@ -541,7 +541,7 @@ static int allocate_now(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
|
static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
_cleanup_close_ int efd = -EBADF;
|
_cleanup_close_ int efd = -EBADF;
|
||||||
uint64_t u;
|
uint64_t u;
|
||||||
int r;
|
int r;
|
||||||
@ -560,7 +560,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
|
|||||||
if (efd < 0)
|
if (efd < 0)
|
||||||
return log_error_errno(errno, "Failed to allocate eventfd(): %m");
|
return log_error_errno(errno, "Failed to allocate eventfd(): %m");
|
||||||
|
|
||||||
r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG, &pid);
|
r = pidref_safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -590,7 +590,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
|
|||||||
|
|
||||||
_cleanup_free_ char *pmap = NULL;
|
_cleanup_free_ char *pmap = NULL;
|
||||||
|
|
||||||
if (asprintf(&pmap, "/proc/" PID_FMT "/uid_map", pid) < 0)
|
if (asprintf(&pmap, "/proc/" PID_FMT "/uid_map", pidref.pid) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = write_string_filef(pmap, 0, UID_FMT " " UID_FMT " %" PRIu32 "\n", userns_info->target_uid, userns_info->start_uid, userns_info->size);
|
r = write_string_filef(pmap, 0, UID_FMT " " UID_FMT " %" PRIu32 "\n", userns_info->target_uid, userns_info->start_uid, userns_info->size);
|
||||||
@ -598,7 +598,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
|
|||||||
return log_error_errno(r, "Failed to write 'uid_map' file of user namespace: %m");
|
return log_error_errno(r, "Failed to write 'uid_map' file of user namespace: %m");
|
||||||
|
|
||||||
pmap = mfree(pmap);
|
pmap = mfree(pmap);
|
||||||
if (asprintf(&pmap, "/proc/" PID_FMT "/gid_map", pid) < 0)
|
if (asprintf(&pmap, "/proc/" PID_FMT "/gid_map", pidref.pid) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = write_string_filef(pmap, 0, GID_FMT " " GID_FMT " %" PRIu32 "\n", userns_info->target_gid, userns_info->start_gid, userns_info->size);
|
r = write_string_filef(pmap, 0, GID_FMT " " GID_FMT " %" PRIu32 "\n", userns_info->target_gid, userns_info->start_gid, userns_info->size);
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "namespace-util.h"
|
#include "namespace-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
#include "tmpfile-util.h"
|
#include "tmpfile-util.h"
|
||||||
@ -56,7 +57,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
_cleanup_(userns_restrict_bpf_freep) struct userns_restrict_bpf *obj = NULL;
|
_cleanup_(userns_restrict_bpf_freep) struct userns_restrict_bpf *obj = NULL;
|
||||||
_cleanup_close_ int userns_fd = -EBADF, host_fd1 = -EBADF, host_tmpfs = -EBADF, afd = -EBADF, bfd = -EBADF;
|
_cleanup_close_ int userns_fd = -EBADF, host_fd1 = -EBADF, host_tmpfs = -EBADF, afd = -EBADF, bfd = -EBADF;
|
||||||
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
|
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
log_set_max_level(LOG_DEBUG);
|
log_set_max_level(LOG_DEBUG);
|
||||||
@ -100,7 +101,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
assert_se(afd >= 0 && bfd >= 0);
|
assert_se(afd >= 0 && bfd >= 0);
|
||||||
|
|
||||||
r = safe_fork("(test)", FORK_DEATHSIG_SIGKILL, &pid);
|
r = pidref_safe_fork("(test)", FORK_DEATHSIG_SIGKILL, &pidref);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
_cleanup_close_ int private_tmpfs = -EBADF;
|
_cleanup_close_ int private_tmpfs = -EBADF;
|
||||||
@ -178,7 +179,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
assert_se(eventfd_write(bfd, 1) >= 0);
|
assert_se(eventfd_write(bfd, 1) >= 0);
|
||||||
|
|
||||||
assert_se(wait_for_terminate_and_check("(test)", pid, WAIT_LOG) >= 0);
|
assert_se(pidref_wait_for_terminate_and_check("(test)", &pidref, WAIT_LOG) >= 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,13 +36,13 @@
|
|||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
#include "os-util.h"
|
#include "os-util.h"
|
||||||
#include "path-lookup.h"
|
#include "path-lookup.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "portable.h"
|
#include "portable.h"
|
||||||
#include "portable-util.h"
|
#include "portable-util.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
#include "selinux-util.h"
|
#include "selinux-util.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "signal-util.h"
|
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "sort-util.h"
|
#include "sort-util.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
@ -400,7 +400,7 @@ static int portable_extract_by_path(
|
|||||||
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
|
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
|
||||||
_cleanup_(rmdir_and_freep) char *tmpdir = NULL;
|
_cleanup_(rmdir_and_freep) char *tmpdir = NULL;
|
||||||
_cleanup_close_pair_ int seq[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int seq[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t child = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
DissectImageFlags flags =
|
DissectImageFlags flags =
|
||||||
DISSECT_IMAGE_READ_ONLY |
|
DISSECT_IMAGE_READ_ONLY |
|
||||||
DISSECT_IMAGE_GENERIC_ROOT |
|
DISSECT_IMAGE_GENERIC_ROOT |
|
||||||
@ -420,8 +420,6 @@ static int portable_extract_by_path(
|
|||||||
/* We now have a loopback block device, let's fork off a child in its own mount namespace, mount it
|
/* We now have a loopback block device, let's fork off a child in its own mount namespace, mount it
|
||||||
* there, and extract the metadata we need. The metadata is sent from the child back to us. */
|
* there, and extract the metadata we need. The metadata is sent from the child back to us. */
|
||||||
|
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
|
||||||
|
|
||||||
/* Load some libraries before we fork workers off that want to use them */
|
/* Load some libraries before we fork workers off that want to use them */
|
||||||
(void) dlopen_cryptsetup();
|
(void) dlopen_cryptsetup();
|
||||||
(void) dlopen_libmount();
|
(void) dlopen_libmount();
|
||||||
@ -454,7 +452,7 @@ static int portable_extract_by_path(
|
|||||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, seq) < 0)
|
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, seq) < 0)
|
||||||
return log_debug_errno(errno, "Failed to allocated SOCK_SEQPACKET socket: %m");
|
return log_debug_errno(errno, "Failed to allocated SOCK_SEQPACKET socket: %m");
|
||||||
|
|
||||||
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child);
|
r = pidref_safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -540,10 +538,11 @@ static int portable_extract_by_path(
|
|||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wait_for_terminate_and_check("(sd-dissect)", child, 0);
|
r = pidref_wait_for_terminate_and_check("(sd-dissect)", &child, 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
child = 0;
|
|
||||||
|
TAKE_PIDREF(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!os_release)
|
if (!os_release)
|
||||||
|
|||||||
@ -488,7 +488,7 @@ int bus_image_common_remove(
|
|||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t child = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
PortableState state;
|
PortableState state;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -533,7 +533,7 @@ int bus_image_common_remove(
|
|||||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||||
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
||||||
|
|
||||||
r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
|
r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -550,11 +550,11 @@ int bus_image_common_remove(
|
|||||||
|
|
||||||
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
||||||
|
|
||||||
r = operation_new(m, child, message, errno_pipe_fd[0], NULL);
|
r = operation_new(m, &child, message, errno_pipe_fd[0], NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
child = 0;
|
TAKE_PIDREF(child);
|
||||||
errno_pipe_fd[0] = -EBADF;
|
errno_pipe_fd[0] = -EBADF;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "sd-event.h"
|
#include "sd-event.h"
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "event-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -22,10 +23,10 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
|
|||||||
assert(si);
|
assert(si);
|
||||||
|
|
||||||
log_debug("Operation " PID_FMT " is now complete with code=%s status=%i",
|
log_debug("Operation " PID_FMT " is now complete with code=%s status=%i",
|
||||||
o->pid,
|
o->pidref.pid,
|
||||||
sigchld_code_to_string(si->si_code), si->si_status);
|
sigchld_code_to_string(si->si_code), si->si_status);
|
||||||
|
|
||||||
o->pid = 0;
|
pidref_done(&o->pidref);
|
||||||
|
|
||||||
if (si->si_code != CLD_EXITED) {
|
if (si->si_code != CLD_EXITED) {
|
||||||
r = sd_bus_error_set(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
|
r = sd_bus_error_set(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
|
||||||
@ -74,12 +75,12 @@ fail:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret) {
|
int operation_new(Manager *manager, PidRef *child, sd_bus_message *message, int errno_fd, Operation **ret) {
|
||||||
Operation *o;
|
Operation *o;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(manager);
|
assert(manager);
|
||||||
assert(child > 1);
|
assert(pidref_is_set(child));
|
||||||
assert(message);
|
assert(message);
|
||||||
assert(errno_fd >= 0);
|
assert(errno_fd >= 0);
|
||||||
|
|
||||||
@ -89,13 +90,13 @@ int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int er
|
|||||||
|
|
||||||
o->extra_fd = -EBADF;
|
o->extra_fd = -EBADF;
|
||||||
|
|
||||||
r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o);
|
r = event_add_child_pidref(manager->event, &o->event_source, child, WEXITED, operation_done, o);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
free(o);
|
free(o);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
o->pid = child;
|
o->pidref = TAKE_PIDREF(*child);
|
||||||
o->message = sd_bus_message_ref(message);
|
o->message = sd_bus_message_ref(message);
|
||||||
o->errno_fd = errno_fd;
|
o->errno_fd = errno_fd;
|
||||||
|
|
||||||
@ -103,7 +104,7 @@ int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int er
|
|||||||
manager->n_operations++;
|
manager->n_operations++;
|
||||||
o->manager = manager;
|
o->manager = manager;
|
||||||
|
|
||||||
log_debug("Started new operation " PID_FMT ".", child);
|
log_debug("Started new operation " PID_FMT ".", o->pidref.pid);
|
||||||
|
|
||||||
/* At this point we took ownership of both the child and the errno file descriptor! */
|
/* At this point we took ownership of both the child and the errno file descriptor! */
|
||||||
|
|
||||||
@ -122,8 +123,7 @@ Operation *operation_free(Operation *o) {
|
|||||||
safe_close(o->errno_fd);
|
safe_close(o->errno_fd);
|
||||||
safe_close(o->extra_fd);
|
safe_close(o->extra_fd);
|
||||||
|
|
||||||
if (o->pid > 1)
|
pidref_done_sigkill_wait(&o->pidref);
|
||||||
sigkill_wait(o->pid);
|
|
||||||
|
|
||||||
sd_bus_message_unref(o->message);
|
sd_bus_message_unref(o->message);
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "portabled-forward.h"
|
#include "portabled-forward.h"
|
||||||
|
|
||||||
#define OPERATIONS_MAX 64
|
#define OPERATIONS_MAX 64
|
||||||
|
|
||||||
typedef struct Operation {
|
typedef struct Operation {
|
||||||
Manager *manager;
|
Manager *manager;
|
||||||
pid_t pid;
|
PidRef pidref;
|
||||||
sd_bus_message *message;
|
sd_bus_message *message;
|
||||||
int errno_fd;
|
int errno_fd;
|
||||||
int extra_fd;
|
int extra_fd;
|
||||||
@ -17,5 +18,5 @@ typedef struct Operation {
|
|||||||
LIST_FIELDS(Operation, operations);
|
LIST_FIELDS(Operation, operations);
|
||||||
} Operation;
|
} Operation;
|
||||||
|
|
||||||
int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret);
|
int operation_new(Manager *manager, PidRef *child, sd_bus_message *message, int errno_fd, Operation **ret);
|
||||||
Operation *operation_free(Operation *o);
|
Operation *operation_free(Operation *o);
|
||||||
|
|||||||
@ -143,8 +143,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (argc != 1)
|
if (argc != 1)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, /* ret_old_mask= */ NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate manager object: %m");
|
return log_error_errno(r, "Failed to allocate manager object: %m");
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "ptyfwd.h"
|
#include "ptyfwd.h"
|
||||||
#include "signal-util.h"
|
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
@ -156,8 +155,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
log_setup();
|
log_setup();
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, /* ret_old_mask= */ NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = parse_argv(argc, argv);
|
r = parse_argv(argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@ -1,19 +1,17 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "ask-password-agent.h"
|
#include "ask-password-agent.h"
|
||||||
#include "bus-util.h"
|
#include "bus-util.h"
|
||||||
#include "exec-util.h"
|
#include "exec-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "process-util.h"
|
#include "pidref.h"
|
||||||
|
|
||||||
static pid_t agent_pid = 0;
|
static PidRef agent_pidref = PIDREF_NULL;
|
||||||
|
|
||||||
int ask_password_agent_open(void) {
|
int ask_password_agent_open(void) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (agent_pid > 0)
|
if (pidref_is_set(&agent_pidref))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = shall_fork_agent();
|
r = shall_fork_agent();
|
||||||
@ -22,7 +20,7 @@ int ask_password_agent_open(void) {
|
|||||||
|
|
||||||
r = fork_agent("(sd-askpwagent)",
|
r = fork_agent("(sd-askpwagent)",
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
&agent_pid,
|
&agent_pidref,
|
||||||
SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH,
|
SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH,
|
||||||
"--watch");
|
"--watch");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -32,12 +30,8 @@ int ask_password_agent_open(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ask_password_agent_close(void) {
|
void ask_password_agent_close(void) {
|
||||||
|
|
||||||
if (agent_pid <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Inform agent that we are done */
|
/* Inform agent that we are done */
|
||||||
sigterm_wait(TAKE_PID(agent_pid));
|
pidref_done_sigterm_wait(&agent_pidref);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ask_password_agent_open_if_enabled(BusTransport transport, bool ask_password) {
|
int ask_password_agent_open_if_enabled(BusTransport transport, bool ask_password) {
|
||||||
|
|||||||
@ -59,11 +59,11 @@
|
|||||||
#include "openssl-util.h"
|
#include "openssl-util.h"
|
||||||
#include "os-util.h"
|
#include "os-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "resize-fs.h"
|
#include "resize-fs.h"
|
||||||
#include "runtime-scope.h"
|
#include "runtime-scope.h"
|
||||||
#include "signal-util.h"
|
|
||||||
#include "siphash24.h"
|
#include "siphash24.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -2237,7 +2237,6 @@ static int is_loop_device(const char *path) {
|
|||||||
|
|
||||||
static int run_fsck(int node_fd, const char *fstype) {
|
static int run_fsck(int node_fd, const char *fstype) {
|
||||||
int r, exit_status;
|
int r, exit_status;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
assert(node_fd >= 0);
|
assert(node_fd >= 0);
|
||||||
assert(fstype);
|
assert(fstype);
|
||||||
@ -2252,12 +2251,13 @@ static int run_fsck(int node_fd, const char *fstype) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork_full(
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork_full(
|
||||||
"(fsck)",
|
"(fsck)",
|
||||||
NULL,
|
NULL,
|
||||||
&node_fd, 1, /* Leave the node fd open */
|
&node_fd, 1, /* Leave the node fd open */
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
|
||||||
&pid);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to fork off fsck: %m");
|
return log_debug_errno(r, "Failed to fork off fsck: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -2268,7 +2268,7 @@ static int run_fsck(int node_fd, const char *fstype) {
|
|||||||
_exit(FSCK_OPERATIONAL_ERROR);
|
_exit(FSCK_OPERATIONAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_status = wait_for_terminate_and_check("fsck", pid, 0);
|
exit_status = pidref_wait_for_terminate_and_check("fsck", &pidref, 0);
|
||||||
if (exit_status < 0)
|
if (exit_status < 0)
|
||||||
return log_debug_errno(exit_status, "Failed to fork off fsck: %m");
|
return log_debug_errno(exit_status, "Failed to fork off fsck: %m");
|
||||||
|
|
||||||
@ -4170,15 +4170,13 @@ int dissected_image_acquire_metadata(
|
|||||||
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **sysext_release = NULL, **confext_release = NULL;
|
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **sysext_release = NULL, **confext_release = NULL;
|
||||||
_cleanup_free_ char *hostname = NULL, *t = NULL;
|
_cleanup_free_ char *hostname = NULL, *t = NULL;
|
||||||
_cleanup_close_pair_ int error_pipe[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int error_pipe[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t child = 0;
|
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
|
||||||
sd_id128_t machine_id = SD_ID128_NULL;
|
sd_id128_t machine_id = SD_ID128_NULL;
|
||||||
unsigned n_meta_initialized = 0;
|
unsigned n_meta_initialized = 0;
|
||||||
int fds[2 * _META_MAX], r, v;
|
int fds[2 * _META_MAX], r, v;
|
||||||
int has_init_system = -1;
|
int has_init_system = -1;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
r = dlopen_libmount();
|
r = dlopen_libmount();
|
||||||
@ -4203,7 +4201,7 @@ int dissected_image_acquire_metadata(
|
|||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &child);
|
r = pidref_safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &child);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -4426,11 +4424,12 @@ int dissected_image_acquire_metadata(
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wait_for_terminate_and_check("(sd-dissect)", child, 0);
|
r = pidref_wait_for_terminate_and_check("(sd-dissect)", &child, 0);
|
||||||
child = 0;
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
|
TAKE_PIDREF(child);
|
||||||
|
|
||||||
n = read(error_pipe[0], &v, sizeof(v));
|
n = read(error_pipe[0], &v, sizeof(v));
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
@ -28,6 +29,10 @@
|
|||||||
|
|
||||||
#define EXIT_SKIP_REMAINING 77
|
#define EXIT_SKIP_REMAINING 77
|
||||||
|
|
||||||
|
DEFINE_PRIVATE_HASH_OPS_FULL(pidref_hash_ops_free_free,
|
||||||
|
PidRef, pidref_hash_func, pidref_compare_func,
|
||||||
|
pidref_free, char*, free);
|
||||||
|
|
||||||
/* Put this test here for a lack of better place */
|
/* Put this test here for a lack of better place */
|
||||||
assert_cc(EAGAIN == EWOULDBLOCK);
|
assert_cc(EAGAIN == EWOULDBLOCK);
|
||||||
|
|
||||||
@ -36,25 +41,25 @@ static int do_spawn(
|
|||||||
char *argv[],
|
char *argv[],
|
||||||
int stdout_fd,
|
int stdout_fd,
|
||||||
bool set_systemd_exec_pid,
|
bool set_systemd_exec_pid,
|
||||||
pid_t *ret_pid) {
|
PidRef *ret) {
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(path);
|
assert(path);
|
||||||
assert(ret_pid);
|
assert(ret);
|
||||||
|
|
||||||
if (null_or_empty_path(path) > 0) {
|
if (null_or_empty_path(path) > 0) {
|
||||||
log_debug("%s is masked, skipping.", path);
|
log_debug("%s is masked, skipping.", path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t pid;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
r = safe_fork_full(
|
r = pidref_safe_fork_full(
|
||||||
"(exec-inner)",
|
"(exec-inner)",
|
||||||
(const int[]) { STDIN_FILENO, stdout_fd < 0 ? STDOUT_FILENO : stdout_fd, STDERR_FILENO },
|
(const int[]) { STDIN_FILENO, stdout_fd < 0 ? STDOUT_FILENO : stdout_fd, STDERR_FILENO },
|
||||||
/* except_fds= */ NULL, /* n_except_fds= */ 0,
|
/* except_fds= */ NULL, /* n_except_fds= */ 0,
|
||||||
FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS,
|
FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS,
|
||||||
&pid);
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -78,7 +83,7 @@ static int do_spawn(
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret_pid = pid;
|
*ret = TAKE_PIDREF(pidref);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +126,6 @@ static int do_execute(
|
|||||||
STRV_FOREACH(path, paths) {
|
STRV_FOREACH(path, paths) {
|
||||||
_cleanup_free_ char *t = NULL;
|
_cleanup_free_ char *t = NULL;
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
t = path_join(root, *path);
|
t = path_join(root, *path);
|
||||||
if (!t)
|
if (!t)
|
||||||
@ -161,19 +165,27 @@ static int do_execute(
|
|||||||
"permission bits. Proceeding anyway.", t);
|
"permission bits. Proceeding anyway.", t);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = do_spawn(t, argv, fd, FLAGS_SET(flags, EXEC_DIR_SET_SYSTEMD_EXEC_PID), &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = do_spawn(t, argv, fd, FLAGS_SET(flags, EXEC_DIR_SET_SYSTEMD_EXEC_PID), &pidref);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (parallel_execution) {
|
if (parallel_execution) {
|
||||||
r = hashmap_ensure_put(&pids, &trivial_hash_ops_value_free, PID_TO_PTR(pid), t);
|
_cleanup_(pidref_freep) PidRef *dup = NULL;
|
||||||
|
r = pidref_dup(&pidref, &dup);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = hashmap_ensure_put(&pids, &pidref_hash_ops_free_free, dup, t);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
t = NULL;
|
|
||||||
|
TAKE_PTR(dup);
|
||||||
|
TAKE_PTR(t);
|
||||||
} else {
|
} else {
|
||||||
bool skip_remaining = false;
|
bool skip_remaining = false;
|
||||||
|
|
||||||
r = wait_for_terminate_and_check(t, pid, WAIT_LOG_ABNORMAL);
|
r = pidref_wait_for_terminate_and_check(t, &pidref, WAIT_LOG_ABNORMAL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
@ -211,14 +223,12 @@ static int do_execute(
|
|||||||
|
|
||||||
while (!hashmap_isempty(pids)) {
|
while (!hashmap_isempty(pids)) {
|
||||||
_cleanup_free_ char *t = NULL;
|
_cleanup_free_ char *t = NULL;
|
||||||
pid_t pid;
|
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
t = ASSERT_PTR(hashmap_steal_first_key_and_value(pids, &p));
|
t = ASSERT_PTR(hashmap_steal_first_key_and_value(pids, &p));
|
||||||
pid = PTR_TO_PID(p);
|
_cleanup_(pidref_freep) PidRef *pidref = p;
|
||||||
assert(pid > 0);
|
|
||||||
|
|
||||||
r = wait_for_terminate_and_check(t, pid, WAIT_LOG);
|
r = pidref_wait_for_terminate_and_check(t, pidref, WAIT_LOG);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0)
|
if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0)
|
||||||
@ -240,7 +250,6 @@ int execute_strv(
|
|||||||
ExecDirFlags flags) {
|
ExecDirFlags flags) {
|
||||||
|
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
pid_t executor_pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(name);
|
assert(name);
|
||||||
@ -266,7 +275,8 @@ int execute_strv(
|
|||||||
|
|
||||||
const char *process_name = strjoina("(", name, ")");
|
const char *process_name = strjoina("(", name, ")");
|
||||||
|
|
||||||
r = safe_fork(process_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &executor_pid);
|
PidRef executor_pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork(process_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &executor_pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -274,7 +284,7 @@ int execute_strv(
|
|||||||
_exit(r < 0 ? EXIT_FAILURE : r);
|
_exit(r < 0 ? EXIT_FAILURE : r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wait_for_terminate_and_check(process_name, executor_pid, 0);
|
r = pidref_wait_for_terminate_and_check(process_name, &executor_pidref, 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0)
|
if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0)
|
||||||
@ -560,19 +570,19 @@ int shall_fork_agent(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, pid_t *ret_pid) {
|
int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, PidRef *ret) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(!strv_isempty(argv));
|
assert(!strv_isempty(argv));
|
||||||
|
|
||||||
/* Spawns a temporary TTY agent, making sure it goes away when we go away */
|
/* Spawns a temporary TTY agent, making sure it goes away when we go away */
|
||||||
|
|
||||||
r = safe_fork_full(name,
|
r = pidref_safe_fork_full(
|
||||||
NULL,
|
name,
|
||||||
(int*) except, /* safe_fork_full only changes except if you pass in FORK_PACK_FDS, which we don't */
|
/* stdio_fds= */ NULL,
|
||||||
n_except,
|
(int*) except, n_except, /* safe_fork_full only changes except if you pass in FORK_PACK_FDS, which we don't */
|
||||||
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE,
|
||||||
ret_pid);
|
ret);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
|
|||||||
@ -62,5 +62,5 @@ ExecCommandFlags exec_command_flags_from_string(const char *s);
|
|||||||
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]);
|
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]);
|
||||||
|
|
||||||
int shall_fork_agent(void);
|
int shall_fork_agent(void);
|
||||||
int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, pid_t *ret_pid);
|
int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, PidRef *ret);
|
||||||
#define fork_agent(name, except, n_except, ret_pid, ...) _fork_agent(name, STRV_MAKE(__VA_ARGS__), except, n_except, ret_pid)
|
#define fork_agent(name, except, n_except, ret, ...) _fork_agent(name, STRV_MAKE(__VA_ARGS__), except, n_except, ret)
|
||||||
|
|||||||
@ -35,7 +35,7 @@ static int on_child_exit(sd_event_source *s, const siginfo_t *si, void *userdata
|
|||||||
else if (si->si_code == CLD_DUMPED)
|
else if (si->si_code == CLD_DUMPED)
|
||||||
log_debug("Child process " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
|
log_debug("Child process " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
|
||||||
else
|
else
|
||||||
log_debug("Got unexpected exit code %i via SIGCHLD, ignoring.", si->si_code);
|
log_debug("Got unexpected exit code %i from child, ignoring.", si->si_code);
|
||||||
|
|
||||||
/* And let's then fail the whole thing, because regardless what the exit status of the child is
|
/* And let's then fail the whole thing, because regardless what the exit status of the child is
|
||||||
* (i.e. even if successful), if it exits before sending READY=1 something is wrong. */
|
* (i.e. even if successful), if it exits before sending READY=1 something is wrong. */
|
||||||
@ -106,7 +106,7 @@ int fork_notify(char * const *argv, PidRef *ret_pidref) {
|
|||||||
_cleanup_free_ char *addr_string = NULL;
|
_cleanup_free_ char *addr_string = NULL;
|
||||||
r = notify_socket_prepare_full(
|
r = notify_socket_prepare_full(
|
||||||
event,
|
event,
|
||||||
SD_EVENT_PRIORITY_NORMAL-10, /* We want the notification message from the child before the SIGCHLD */
|
SD_EVENT_PRIORITY_NORMAL-10, /* We want the notification message from the child before the child exit */
|
||||||
on_child_notify,
|
on_child_notify,
|
||||||
&child,
|
&child,
|
||||||
/* accept_fds= */ false,
|
/* accept_fds= */ false,
|
||||||
@ -124,8 +124,6 @@ int fork_notify(char * const *argv, PidRef *ret_pidref) {
|
|||||||
log_debug("Invoking '%s' as child.", strnull(l));
|
log_debug("Invoking '%s' as child.", strnull(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
|
||||||
|
|
||||||
r = pidref_safe_fork_full(
|
r = pidref_safe_fork_full(
|
||||||
"(fork-notify)",
|
"(fork-notify)",
|
||||||
(const int[3]) { -EBADF, STDOUT_FILENO, STDERR_FILENO },
|
(const int[3]) { -EBADF, STDOUT_FILENO, STDERR_FILENO },
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include "locale-util.h"
|
#include "locale-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -288,8 +289,10 @@ void pager_close(void) {
|
|||||||
stdout_redirected = stderr_redirected = false;
|
stdout_redirected = stderr_redirected = false;
|
||||||
|
|
||||||
(void) kill(pager_pid, SIGCONT);
|
(void) kill(pager_pid, SIGCONT);
|
||||||
(void) wait_for_terminate(TAKE_PID(pager_pid), NULL);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pager_pid);
|
||||||
pager_pid = 0;
|
(void) pidref_set_pid(&pidref, pager_pid);
|
||||||
|
(void) pidref_wait_for_terminate(&pidref, NULL);
|
||||||
|
TAKE_PID(pager_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pager_have(void) {
|
bool pager_have(void) {
|
||||||
@ -299,7 +302,6 @@ bool pager_have(void) {
|
|||||||
int show_man_page(const char *desc, bool null_stdio) {
|
int show_man_page(const char *desc, bool null_stdio) {
|
||||||
const char *args[4] = { "man", NULL, NULL, NULL };
|
const char *args[4] = { "man", NULL, NULL, NULL };
|
||||||
const char *e = NULL;
|
const char *e = NULL;
|
||||||
pid_t pid;
|
|
||||||
size_t k;
|
size_t k;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -319,7 +321,11 @@ int show_man_page(const char *desc, bool null_stdio) {
|
|||||||
} else
|
} else
|
||||||
args[1] = desc;
|
args[1] = desc;
|
||||||
|
|
||||||
r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork(
|
||||||
|
"(man)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT,
|
||||||
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -329,5 +335,5 @@ int show_man_page(const char *desc, bool null_stdio) {
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wait_for_terminate_and_check(NULL, pid, 0);
|
return pidref_wait_for_terminate_and_check(NULL, &pidref, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "bus-util.h"
|
#include "bus-util.h"
|
||||||
@ -9,19 +8,19 @@
|
|||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "polkit-agent.h"
|
#include "polkit-agent.h"
|
||||||
#include "process-util.h"
|
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
|
|
||||||
#if ENABLE_POLKIT
|
#if ENABLE_POLKIT
|
||||||
static pid_t agent_pid = 0;
|
static PidRef agent_pidref = PIDREF_NULL;
|
||||||
|
|
||||||
int polkit_agent_open(void) {
|
int polkit_agent_open(void) {
|
||||||
_cleanup_close_pair_ int pipe_fd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int pipe_fd[2] = EBADF_PAIR;
|
||||||
char notify_fd[DECIMAL_STR_MAX(int) + 1];
|
char notify_fd[DECIMAL_STR_MAX(int) + 1];
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (agent_pid > 0)
|
if (pidref_is_set(&agent_pidref))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Clients that run as root don't need to activate/query polkit */
|
/* Clients that run as root don't need to activate/query polkit */
|
||||||
@ -40,7 +39,7 @@ int polkit_agent_open(void) {
|
|||||||
r = fork_agent("(polkit-agent)",
|
r = fork_agent("(polkit-agent)",
|
||||||
&pipe_fd[1],
|
&pipe_fd[1],
|
||||||
1,
|
1,
|
||||||
&agent_pid,
|
&agent_pidref,
|
||||||
POLKIT_AGENT_BINARY_PATH,
|
POLKIT_AGENT_BINARY_PATH,
|
||||||
"--notify-fd", notify_fd,
|
"--notify-fd", notify_fd,
|
||||||
"--fallback");
|
"--fallback");
|
||||||
@ -57,12 +56,8 @@ int polkit_agent_open(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void polkit_agent_close(void) {
|
void polkit_agent_close(void) {
|
||||||
|
|
||||||
if (agent_pid <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Inform agent that we are done */
|
/* Inform agent that we are done */
|
||||||
sigterm_wait(TAKE_PID(agent_pid));
|
pidref_done_sigterm_wait(&agent_pidref);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -448,7 +448,12 @@ int assert_signal_internal(int *ret_signal) {
|
|||||||
return ASSERT_SIGNAL_FORK_CHILD;
|
return ASSERT_SIGNAL_FORK_CHILD;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wait_for_terminate(r, &siginfo);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_set_pid(&pidref, r);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = pidref_wait_for_terminate(&pidref, &siginfo);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -228,8 +228,6 @@ int sync_with_progress(int fd) {
|
|||||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
|
||||||
|
|
||||||
/* Due to the possibility of the sync operation hanging, we fork a child process and monitor
|
/* Due to the possibility of the sync operation hanging, we fork a child process and monitor
|
||||||
* the progress. If the timeout lapses, the assumption is that the particular sync stalled. */
|
* the progress. If the timeout lapses, the assumption is that the particular sync stalled. */
|
||||||
|
|
||||||
@ -252,12 +250,15 @@ int sync_with_progress(int fd) {
|
|||||||
* SYNC_PROGRESS_ATTEMPTS lapse without progress being made,
|
* SYNC_PROGRESS_ATTEMPTS lapse without progress being made,
|
||||||
* we assume that the sync is stalled */
|
* we assume that the sync is stalled */
|
||||||
for (unsigned checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) {
|
for (unsigned checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) {
|
||||||
r = wait_for_terminate_with_timeout(pidref.pid, SYNC_TIMEOUT_USEC);
|
siginfo_t si;
|
||||||
if (r == 0)
|
|
||||||
|
r = pidref_wait_for_terminate_full(&pidref, SYNC_TIMEOUT_USEC, &si);
|
||||||
|
if (r >= 0 && si.si_code == CLD_EXITED && si.si_status == EXIT_SUCCESS)
|
||||||
/* Sync finished without error (sync() call itself does not return an error code) */
|
/* Sync finished without error (sync() call itself does not return an error code) */
|
||||||
return 0;
|
return 0;
|
||||||
if (r != -ETIMEDOUT)
|
if (r != -ETIMEDOUT)
|
||||||
return log_error_errno(r, "Failed to sync %s: %m", what);
|
return log_error_errno(r < 0 ? r : SYNTHETIC_ERRNO(EPROTO),
|
||||||
|
"Failed to sync %s: %m", what);
|
||||||
|
|
||||||
/* Reset the check counter if we made some progress */
|
/* Reset the check counter if we made some progress */
|
||||||
if (sync_making_progress(&dirty) > 0)
|
if (sync_making_progress(&dirty) > 0)
|
||||||
|
|||||||
@ -24,9 +24,9 @@
|
|||||||
#include "mount-util.h"
|
#include "mount-util.h"
|
||||||
#include "mountpoint-util.h"
|
#include "mountpoint-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "random-util.h"
|
#include "random-util.h"
|
||||||
#include "signal-util.h"
|
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "umount.h"
|
#include "umount.h"
|
||||||
@ -250,11 +250,9 @@ static void log_umount_blockers(const char *mnt) {
|
|||||||
|
|
||||||
static int remount_with_timeout(MountPoint *m, bool last_try) {
|
static int remount_with_timeout(MountPoint *m, bool last_try) {
|
||||||
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_nowaitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_nowait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
r = pipe2(pfd, O_CLOEXEC|O_NONBLOCK);
|
r = pipe2(pfd, O_CLOEXEC|O_NONBLOCK);
|
||||||
@ -263,10 +261,10 @@ static int remount_with_timeout(MountPoint *m, bool last_try) {
|
|||||||
|
|
||||||
/* Due to the possibility of a remount operation hanging, we fork a child process and set a
|
/* Due to the possibility of a remount operation hanging, we fork a child process and set a
|
||||||
* timeout. If the timeout lapses, the assumption is that the particular remount failed. */
|
* timeout. If the timeout lapses, the assumption is that the particular remount failed. */
|
||||||
r = safe_fork_full("(sd-remount)",
|
r = pidref_safe_fork_full("(sd-remount)",
|
||||||
NULL,
|
NULL,
|
||||||
pfd, ELEMENTSOF(pfd),
|
pfd, ELEMENTSOF(pfd),
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -287,29 +285,37 @@ static int remount_with_timeout(MountPoint *m, bool last_try) {
|
|||||||
|
|
||||||
pfd[1] = safe_close(pfd[1]);
|
pfd[1] = safe_close(pfd[1]);
|
||||||
|
|
||||||
r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC);
|
siginfo_t si;
|
||||||
|
r = pidref_wait_for_terminate_full(&pidref, DEFAULT_TIMEOUT_USEC, &si);
|
||||||
if (r == -ETIMEDOUT)
|
if (r == -ETIMEDOUT)
|
||||||
log_error_errno(r, "Remounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid);
|
log_error_errno(r, "Remounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pidref.pid);
|
||||||
else if (r == -EPROTO) {
|
else if (r < 0)
|
||||||
|
log_error_errno(r, "Remounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pidref.pid);
|
||||||
|
else if (si.si_code != CLD_EXITED || si.si_status != 0) {
|
||||||
/* Try to read error code from child */
|
/* Try to read error code from child */
|
||||||
if (read(pfd[0], &r, sizeof(r)) == sizeof(r))
|
r = read_errno(pfd[0]);
|
||||||
log_debug_errno(r, "Remounting '%s' failed abnormally, child process " PID_FMT " failed: %m", m->path, pid);
|
if (r == -EIO)
|
||||||
else
|
r = log_debug_errno(
|
||||||
r = log_debug_errno(EPROTO, "Remounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid);
|
SYNTHETIC_ERRNO(EPROTO),
|
||||||
TAKE_PID(pid); /* child exited (just not as we expected) hence don't kill anymore */
|
"Remounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.",
|
||||||
} else if (r < 0)
|
m->path, pidref.pid);
|
||||||
log_error_errno(r, "Remounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid);
|
else if (r < 0)
|
||||||
|
log_debug_errno(
|
||||||
|
r,
|
||||||
|
"Remounting '%s' failed abnormally, child process " PID_FMT " failed: %m",
|
||||||
|
m->path, pidref.pid);
|
||||||
|
|
||||||
|
TAKE_PIDREF(pidref); /* child exited (just not as we expected) hence don't kill anymore */
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int umount_with_timeout(MountPoint *m, bool last_try) {
|
static int umount_with_timeout(MountPoint *m, bool last_try) {
|
||||||
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_nowaitp) pid_t pid = 0;
|
_cleanup_(pidref_done_sigkill_nowait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
r = pipe2(pfd, O_CLOEXEC|O_NONBLOCK);
|
r = pipe2(pfd, O_CLOEXEC|O_NONBLOCK);
|
||||||
@ -318,10 +324,10 @@ static int umount_with_timeout(MountPoint *m, bool last_try) {
|
|||||||
|
|
||||||
/* Due to the possibility of a umount operation hanging, we fork a child process and set a
|
/* Due to the possibility of a umount operation hanging, we fork a child process and set a
|
||||||
* timeout. If the timeout lapses, the assumption is that the particular umount failed. */
|
* timeout. If the timeout lapses, the assumption is that the particular umount failed. */
|
||||||
r = safe_fork_full("(sd-umount)",
|
r = pidref_safe_fork_full("(sd-umount)",
|
||||||
NULL,
|
NULL,
|
||||||
pfd, ELEMENTSOF(pfd),
|
pfd, ELEMENTSOF(pfd),
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -349,18 +355,28 @@ static int umount_with_timeout(MountPoint *m, bool last_try) {
|
|||||||
|
|
||||||
pfd[1] = safe_close(pfd[1]);
|
pfd[1] = safe_close(pfd[1]);
|
||||||
|
|
||||||
r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC);
|
siginfo_t si;
|
||||||
|
r = pidref_wait_for_terminate_full(&pidref, DEFAULT_TIMEOUT_USEC, &si);
|
||||||
if (r == -ETIMEDOUT)
|
if (r == -ETIMEDOUT)
|
||||||
log_error_errno(r, "Unmounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid);
|
log_error_errno(r, "Unmounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pidref.pid);
|
||||||
else if (r == -EPROTO) {
|
else if (r < 0)
|
||||||
|
log_error_errno(r, "Unmounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pidref.pid);
|
||||||
|
else if (si.si_code != CLD_EXITED || si.si_status != 0) {
|
||||||
/* Try to read error code from child */
|
/* Try to read error code from child */
|
||||||
if (read(pfd[0], &r, sizeof(r)) == sizeof(r))
|
r = read_errno(pfd[0]);
|
||||||
log_debug_errno(r, "Unmounting '%s' failed abnormally, child process " PID_FMT " failed: %m", m->path, pid);
|
if (r == -EIO)
|
||||||
else
|
r = log_debug_errno(
|
||||||
r = log_debug_errno(EPROTO, "Unmounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid);
|
SYNTHETIC_ERRNO(EPROTO),
|
||||||
TAKE_PID(pid); /* It died, but abnormally, no purpose in killing */
|
"Unmounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.",
|
||||||
} else if (r < 0)
|
m->path, pidref.pid);
|
||||||
log_error_errno(r, "Unmounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid);
|
else if (r < 0)
|
||||||
|
log_debug_errno(
|
||||||
|
r,
|
||||||
|
"Unmounting '%s' failed abnormally, child process " PID_FMT " failed: %m",
|
||||||
|
m->path, pidref.pid);
|
||||||
|
|
||||||
|
TAKE_PIDREF(pidref); /* It died, but abnormally, no purpose in killing */
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include "initrd-util.h"
|
#include "initrd-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "special.h"
|
#include "special.h"
|
||||||
@ -66,10 +67,10 @@ static int start_target(sd_bus *bus, const char *target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int fork_wait(const char* const cmdline[]) {
|
static int fork_wait(const char* const cmdline[]) {
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -79,7 +80,7 @@ static int fork_wait(const char* const cmdline[]) {
|
|||||||
_exit(EXIT_FAILURE); /* Operational error */
|
_exit(EXIT_FAILURE); /* Operational error */
|
||||||
}
|
}
|
||||||
|
|
||||||
return wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL);
|
return pidref_wait_for_terminate_and_check(cmdline[0], &pidref, WAIT_LOG_ABNORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_mode(const char* mode) {
|
static void print_mode(const char* mode) {
|
||||||
|
|||||||
@ -48,6 +48,7 @@
|
|||||||
#include "parse-argument.h"
|
#include "parse-argument.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
@ -2139,14 +2140,15 @@ static int merge(ImageClass image_class,
|
|||||||
bool no_reload,
|
bool no_reload,
|
||||||
int noexec,
|
int noexec,
|
||||||
Hashmap *images) {
|
Hashmap *images) {
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
(void) dlopen_cryptsetup();
|
(void) dlopen_cryptsetup();
|
||||||
(void) dlopen_libblkid();
|
(void) dlopen_libblkid();
|
||||||
(void) dlopen_libmount();
|
(void) dlopen_libmount();
|
||||||
|
|
||||||
r = safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to fork off child: %m");
|
return log_error_errno(r, "Failed to fork off child: %m");
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -2162,7 +2164,7 @@ static int merge(ImageClass image_class,
|
|||||||
_exit(r > 0 ? EXIT_SUCCESS : 123); /* 123 means: didn't find any extensions */
|
_exit(r > 0 ? EXIT_SUCCESS : 123); /* 123 means: didn't find any extensions */
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wait_for_terminate_and_check("(sd-merge)", pid, WAIT_LOG_ABNORMAL);
|
r = pidref_wait_for_terminate_and_check("(sd-merge)", &pidref, WAIT_LOG_ABNORMAL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 123) /* exit code 123 means: didn't do anything */
|
if (r == 123) /* exit code 123 means: didn't do anything */
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -9,6 +8,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "path-lookup.h"
|
#include "path-lookup.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
@ -56,7 +56,6 @@ int enable_sysv_units(const char *verb, char **args) {
|
|||||||
bool found_native = false, found_sysv;
|
bool found_native = false, found_sysv;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned c = 1;
|
unsigned c = 1;
|
||||||
pid_t pid;
|
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
name = args[f++];
|
name = args[f++];
|
||||||
@ -122,7 +121,8 @@ int enable_sysv_units(const char *verb, char **args) {
|
|||||||
if (!arg_quiet)
|
if (!arg_quiet)
|
||||||
log_info("Executing: %s", l);
|
log_info("Executing: %s", l);
|
||||||
|
|
||||||
j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
j = pidref_safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
|
||||||
if (j < 0)
|
if (j < 0)
|
||||||
return j;
|
return j;
|
||||||
if (j == 0) {
|
if (j == 0) {
|
||||||
@ -132,7 +132,7 @@ int enable_sysv_units(const char *verb, char **args) {
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL);
|
j = pidref_wait_for_terminate_and_check("sysv-install", &pidref, WAIT_LOG_ABNORMAL);
|
||||||
if (j < 0)
|
if (j < 0)
|
||||||
return j;
|
return j;
|
||||||
if (streq(verb, "is-enabled")) {
|
if (streq(verb, "is-enabled")) {
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
#include "hexdecoct.h"
|
#include "hexdecoct.h"
|
||||||
#include "import-util.h"
|
#include "import-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "sort-util.h"
|
#include "sort-util.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
@ -274,7 +275,6 @@ static int download_manifest(
|
|||||||
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
|
||||||
_cleanup_fclose_ FILE *manifest = NULL;
|
_cleanup_fclose_ FILE *manifest = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(url);
|
assert(url);
|
||||||
@ -293,11 +293,13 @@ static int download_manifest(
|
|||||||
log_info("%s Acquiring manifest file %s%s", glyph(GLYPH_DOWNLOAD),
|
log_info("%s Acquiring manifest file %s%s", glyph(GLYPH_DOWNLOAD),
|
||||||
suffixed_url, glyph(GLYPH_ELLIPSIS));
|
suffixed_url, glyph(GLYPH_ELLIPSIS));
|
||||||
|
|
||||||
r = safe_fork_full("(sd-pull)",
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
(int[]) { -EBADF, pfd[1], STDERR_FILENO },
|
r = pidref_safe_fork_full(
|
||||||
NULL, 0,
|
"(sd-pull)",
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG,
|
(int[]) { -EBADF, pfd[1], STDERR_FILENO },
|
||||||
&pid);
|
NULL, 0,
|
||||||
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG,
|
||||||
|
&pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -337,7 +339,7 @@ static int download_manifest(
|
|||||||
|
|
||||||
manifest = safe_fclose(manifest);
|
manifest = safe_fclose(manifest);
|
||||||
|
|
||||||
r = wait_for_terminate_and_check("(sd-pull)", pid, WAIT_LOG);
|
r = pidref_wait_for_terminate_and_check("(sd-pull)", &pidref, WAIT_LOG);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
|
|||||||
@ -23,7 +23,6 @@
|
|||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "signal-util.h"
|
|
||||||
#include "sort-util.h"
|
#include "sort-util.h"
|
||||||
#include "specifier.h"
|
#include "specifier.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@ -1877,9 +1876,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* SIGCHLD signal must be blocked for sd_event_add_child to work */
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
return sysupdate_main(argc, argv);
|
return sysupdate_main(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1738,7 +1738,7 @@ static int manager_new(Manager **ret) {
|
|||||||
|
|
||||||
r = notify_socket_prepare(
|
r = notify_socket_prepare(
|
||||||
m->event,
|
m->event,
|
||||||
SD_EVENT_PRIORITY_NORMAL - 1, /* Make this processed before SIGCHLD. */
|
SD_EVENT_PRIORITY_NORMAL - 1, /* Make this processed before worker exit. */
|
||||||
manager_on_notify,
|
manager_on_notify,
|
||||||
m,
|
m,
|
||||||
&m->notify_socket_path);
|
&m->notify_socket_path);
|
||||||
@ -2078,9 +2078,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
umask(0022);
|
umask(0022);
|
||||||
|
|
||||||
/* SIGCHLD signal must be blocked for sd_event_add_child to work */
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate manager object: %m");
|
return log_error_errno(r, "Failed to allocate manager object: %m");
|
||||||
|
|||||||
@ -59,53 +59,38 @@ static void test_rename_process_now(const char *p, int ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_rename_process_one(const char *p, int ret) {
|
static void test_rename_process_one(const char *p, int ret) {
|
||||||
siginfo_t si;
|
int r;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
log_info("/* %s(%s) */", __func__, p);
|
log_info("/* %s(%s) */", __func__, p);
|
||||||
|
|
||||||
pid = fork();
|
r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
|
||||||
assert_se(pid >= 0);
|
|
||||||
|
|
||||||
if (pid == 0) {
|
if (r == 0) {
|
||||||
/* child */
|
/* child */
|
||||||
test_rename_process_now(p, ret);
|
test_rename_process_now(p, ret);
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(wait_for_terminate(pid, &si) >= 0);
|
|
||||||
assert_se(si.si_code == CLD_EXITED);
|
|
||||||
assert_se(si.si_status == EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(rename_process_invalid) {
|
TEST(rename_process_invalid) {
|
||||||
assert_se(rename_process(NULL) == -EINVAL);
|
ASSERT_ERROR(rename_process(NULL), EINVAL);
|
||||||
assert_se(rename_process("") == -EINVAL);
|
ASSERT_ERROR(rename_process(""), EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(rename_process_multi) {
|
TEST(rename_process_multi) {
|
||||||
pid_t pid;
|
int r;
|
||||||
|
|
||||||
pid = fork();
|
r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
|
||||||
assert_se(pid >= 0);
|
|
||||||
|
|
||||||
if (pid > 0) {
|
if (r == 0) {
|
||||||
siginfo_t si;
|
/* child */
|
||||||
|
test_rename_process_now("one", 1);
|
||||||
assert_se(wait_for_terminate(pid, &si) >= 0);
|
test_rename_process_now("more", 0); /* longer than "one", hence truncated */
|
||||||
assert_se(si.si_code == CLD_EXITED);
|
(void) setresuid(99, 99, 99); /* change uid when running privileged */
|
||||||
assert_se(si.si_status == EXIT_SUCCESS);
|
test_rename_process_now("time!", 0);
|
||||||
|
test_rename_process_now("0", 1); /* shorter than "one", should fit */
|
||||||
return;
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* child */
|
|
||||||
test_rename_process_now("one", 1);
|
|
||||||
test_rename_process_now("more", 0); /* longer than "one", hence truncated */
|
|
||||||
(void) setresuid(99, 99, 99); /* change uid when running privileged */
|
|
||||||
test_rename_process_now("time!", 0);
|
|
||||||
test_rename_process_now("0", 1); /* shorter than "one", should fit */
|
|
||||||
_exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(rename_process) {
|
TEST(rename_process) {
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
TEST(asynchronous_sync) {
|
TEST(asynchronous_sync) {
|
||||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
ASSERT_OK(asynchronous_sync(&pidref));
|
ASSERT_OK(asynchronous_sync(&pidref));
|
||||||
ASSERT_OK(pidref_wait_for_terminate(&pidref, /* ret= */ NULL));
|
ASSERT_OK(pidref_wait_for_terminate(&pidref, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wait_fd_closed(int fd) {
|
static void wait_fd_closed(int fd) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "data-fd-util.h"
|
#include "data-fd-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "memfd-util.h"
|
#include "memfd-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ static void assert_equal_fd(int fd1, int fd2) {
|
|||||||
TEST(copy_data_fd) {
|
TEST(copy_data_fd) {
|
||||||
_cleanup_close_ int fd1 = -EBADF, fd2 = -EBADF;
|
_cleanup_close_ int fd1 = -EBADF, fd2 = -EBADF;
|
||||||
_cleanup_close_pair_ int sfd[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int sfd[2] = EBADF_PAIR;
|
||||||
_cleanup_(sigkill_waitp) pid_t pid = -1;
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
|
fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
|
||||||
@ -66,7 +67,7 @@ TEST(copy_data_fd) {
|
|||||||
|
|
||||||
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
|
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
|
||||||
|
|
||||||
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid);
|
r = pidref_safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pidref);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
|
|||||||
@ -246,18 +246,17 @@ static bool apparmor_restrict_unprivileged_userns(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool have_userns_privileges(void) {
|
static bool have_userns_privileges(void) {
|
||||||
pid_t pid;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (apparmor_restrict_unprivileged_userns())
|
if (apparmor_restrict_unprivileged_userns())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
r = safe_fork("(sd-test-check-userns)",
|
r = ASSERT_OK(pidref_safe_fork(
|
||||||
FORK_RESET_SIGNALS |
|
"(sd-test-check-userns)",
|
||||||
FORK_CLOSE_ALL_FDS |
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
|
||||||
FORK_DEATHSIG_SIGKILL,
|
&pidref));
|
||||||
&pid);
|
|
||||||
ASSERT_OK(r);
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
/* Keep CAP_SYS_ADMIN if we have it to ensure we give an
|
/* Keep CAP_SYS_ADMIN if we have it to ensure we give an
|
||||||
* accurate result to the caller. Some kernels have a
|
* accurate result to the caller. Some kernels have a
|
||||||
@ -282,7 +281,7 @@ static bool have_userns_privileges(void) {
|
|||||||
* EXIT_SUCCESS => we can use user namespaces
|
* EXIT_SUCCESS => we can use user namespaces
|
||||||
* EXIT_FAILURE => we can NOT use user namespaces
|
* EXIT_FAILURE => we can NOT use user namespaces
|
||||||
* 2 => some other error occurred */
|
* 2 => some other error occurred */
|
||||||
r = wait_for_terminate_and_check("(sd-test-check-userns)", pid, 0);
|
r = pidref_wait_for_terminate_and_check("(sd-test-check-userns)", &pidref, 0);
|
||||||
if (!IN_SET(r, EXIT_SUCCESS, EXIT_FAILURE))
|
if (!IN_SET(r, EXIT_SUCCESS, EXIT_FAILURE))
|
||||||
log_debug("Failed to check if user namespaces can be used, assuming not.");
|
log_debug("Failed to check if user namespaces can be used, assuming not.");
|
||||||
|
|
||||||
@ -681,7 +680,7 @@ static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
static int on_spawn_exit(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
|
|
||||||
ASSERT_NOT_NULL(si);
|
ASSERT_NOT_NULL(si);
|
||||||
@ -707,8 +706,6 @@ static int find_libraries(const char *exec, char ***ret) {
|
|||||||
ASSERT_NOT_NULL(exec);
|
ASSERT_NOT_NULL(exec);
|
||||||
ASSERT_NOT_NULL(ret);
|
ASSERT_NOT_NULL(ret);
|
||||||
|
|
||||||
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
|
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(pipe2(outpipe, O_NONBLOCK|O_CLOEXEC));
|
ASSERT_OK_ERRNO(pipe2(outpipe, O_NONBLOCK|O_CLOEXEC));
|
||||||
ASSERT_OK_ERRNO(pipe2(errpipe, O_NONBLOCK|O_CLOEXEC));
|
ASSERT_OK_ERRNO(pipe2(errpipe, O_NONBLOCK|O_CLOEXEC));
|
||||||
|
|
||||||
@ -733,8 +730,8 @@ static int find_libraries(const char *exec, char ***ret) {
|
|||||||
ASSERT_OK(sd_event_source_set_enabled(stdout_source, SD_EVENT_ONESHOT));
|
ASSERT_OK(sd_event_source_set_enabled(stdout_source, SD_EVENT_ONESHOT));
|
||||||
ASSERT_OK(sd_event_add_io(e, &stderr_source, errpipe[0], EPOLLIN, on_spawn_io, NULL));
|
ASSERT_OK(sd_event_add_io(e, &stderr_source, errpipe[0], EPOLLIN, on_spawn_io, NULL));
|
||||||
ASSERT_OK(sd_event_source_set_enabled(stderr_source, SD_EVENT_ONESHOT));
|
ASSERT_OK(sd_event_source_set_enabled(stderr_source, SD_EVENT_ONESHOT));
|
||||||
ASSERT_OK(sd_event_add_child(e, &sigchld_source, pid, WEXITED, on_spawn_sigchld, NULL));
|
ASSERT_OK(sd_event_add_child(e, &sigchld_source, pid, WEXITED, on_spawn_exit, NULL));
|
||||||
/* SIGCHLD should be processed after IO is complete */
|
/* Child exit should be processed after IO is complete */
|
||||||
ASSERT_OK(sd_event_source_set_priority(sigchld_source, SD_EVENT_PRIORITY_NORMAL + 1));
|
ASSERT_OK(sd_event_source_set_priority(sigchld_source, SD_EVENT_PRIORITY_NORMAL + 1));
|
||||||
|
|
||||||
ASSERT_OK(sd_event_loop(e));
|
ASSERT_OK(sd_event_loop(e));
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "memfd-util.h"
|
#include "memfd-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "random-util.h"
|
#include "random-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
@ -492,7 +493,6 @@ TEST(read_full_file_socket) {
|
|||||||
union sockaddr_union sa;
|
union sockaddr_union sa;
|
||||||
const char *j, *jj;
|
const char *j, *jj;
|
||||||
size_t size;
|
size_t size;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
ASSERT_OK(listener = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
|
ASSERT_OK(listener = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
|
||||||
@ -513,7 +513,8 @@ TEST(read_full_file_socket) {
|
|||||||
/* Bind the *client* socket to some randomized name, to verify that this works correctly. */
|
/* Bind the *client* socket to some randomized name, to verify that this works correctly. */
|
||||||
ASSERT_OK(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()));
|
ASSERT_OK(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()));
|
||||||
|
|
||||||
ASSERT_OK(r = safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid));
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = ASSERT_OK(pidref_safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pidref));
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
union sockaddr_union peer = {};
|
union sockaddr_union peer = {};
|
||||||
socklen_t peerlen = sizeof(peer);
|
socklen_t peerlen = sizeof(peer);
|
||||||
@ -540,7 +541,7 @@ TEST(read_full_file_socket) {
|
|||||||
ASSERT_EQ(size, strlen(TEST_STR));
|
ASSERT_EQ(size, strlen(TEST_STR));
|
||||||
ASSERT_STREQ(data, TEST_STR);
|
ASSERT_STREQ(data, TEST_STR);
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate_and_check("(server)", pid, WAIT_LOG));
|
ASSERT_OK(pidref_wait_for_terminate_and_check("(server)", &pidref, WAIT_LOG));
|
||||||
#undef TEST_STR
|
#undef TEST_STR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "random-util.h"
|
#include "random-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
@ -743,30 +744,29 @@ TEST(xopenat_lock_full) {
|
|||||||
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
|
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
|
||||||
_cleanup_close_ int tfd = -EBADF, fd = -EBADF;
|
_cleanup_close_ int tfd = -EBADF, fd = -EBADF;
|
||||||
siginfo_t si;
|
siginfo_t si;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert_se((tfd = mkdtemp_open(NULL, 0, &t)) >= 0);
|
ASSERT_OK((tfd = mkdtemp_open(NULL, 0, &t)));
|
||||||
|
|
||||||
/* Test that we can acquire an exclusive lock on a directory in one process, remove the directory,
|
/* Test that we can acquire an exclusive lock on a directory in one process, remove the directory,
|
||||||
* and close the file descriptor and still properly create the directory and acquire the lock in
|
* and close the file descriptor and still properly create the directory and acquire the lock in
|
||||||
* another process. */
|
* another process. */
|
||||||
|
|
||||||
fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
|
fd = ASSERT_OK(xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX));
|
||||||
assert_se(fd >= 0);
|
ASSERT_OK_ERRNO(faccessat(tfd, "abc", F_OK, 0));
|
||||||
assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
|
ASSERT_OK(fd_verify_directory(fd));
|
||||||
assert_se(fd_verify_directory(fd) >= 0);
|
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN);
|
||||||
assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
|
|
||||||
|
|
||||||
pid_t pid = fork();
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
assert_se(pid >= 0);
|
r = ASSERT_OK(pidref_safe_fork("(lock)", FORK_DEATHSIG_SIGKILL|FORK_LOG, &pidref));
|
||||||
|
|
||||||
if (pid == 0) {
|
if (r == 0) {
|
||||||
safe_close(fd);
|
safe_close(fd);
|
||||||
|
|
||||||
fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
|
fd = ASSERT_OK(xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX));
|
||||||
assert_se(fd >= 0);
|
ASSERT_OK_ERRNO(faccessat(tfd, "abc", F_OK, 0));
|
||||||
assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
|
ASSERT_OK(fd_verify_directory(fd));
|
||||||
assert_se(fd_verify_directory(fd) >= 0);
|
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN);
|
||||||
assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
|
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
@ -777,16 +777,16 @@ TEST(xopenat_lock_full) {
|
|||||||
* for a little and assume that's enough time for the child process to get along far enough. It
|
* for a little and assume that's enough time for the child process to get along far enough. It
|
||||||
* doesn't matter if it doesn't get far enough, in that case we just won't trigger the fallback logic
|
* doesn't matter if it doesn't get far enough, in that case we just won't trigger the fallback logic
|
||||||
* in xopenat_lock_full(), but the test will still succeed. */
|
* in xopenat_lock_full(), but the test will still succeed. */
|
||||||
assert_se(usleep_safe(20 * USEC_PER_MSEC) >= 0);
|
ASSERT_OK(usleep_safe(20 * USEC_PER_MSEC));
|
||||||
|
|
||||||
assert_se(unlinkat(tfd, "abc", AT_REMOVEDIR) >= 0);
|
ASSERT_OK(unlinkat(tfd, "abc", AT_REMOVEDIR));
|
||||||
fd = safe_close(fd);
|
fd = safe_close(fd);
|
||||||
|
|
||||||
assert_se(wait_for_terminate(pid, &si) >= 0);
|
ASSERT_OK(pidref_wait_for_terminate(&pidref, &si));
|
||||||
assert_se(si.si_code == CLD_EXITED);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
|
|
||||||
assert_se(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
|
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX), EBADF);
|
||||||
assert_se(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
|
ASSERT_ERROR(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX), EBADF);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(linkat_replace) {
|
TEST(linkat_replace) {
|
||||||
|
|||||||
@ -234,7 +234,6 @@ TEST(real_pressure) {
|
|||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
assert_se(sd_event_add_child(e, &cs, pid, WEXITED, real_pressure_child_callback, NULL) >= 0);
|
assert_se(sd_event_add_child(e, &cs, pid, WEXITED, real_pressure_child_callback, NULL) >= 0);
|
||||||
assert_se(sd_event_source_set_child_process_own(cs, true) >= 0);
|
assert_se(sd_event_source_set_child_process_own(cs, true) >= 0);
|
||||||
|
|
||||||
|
|||||||
@ -94,7 +94,7 @@ TEST(tmpdir) {
|
|||||||
static void test_shareable_ns(unsigned long nsflag) {
|
static void test_shareable_ns(unsigned long nsflag) {
|
||||||
_cleanup_close_pair_ int s[2] = EBADF_PAIR;
|
_cleanup_close_pair_ int s[2] = EBADF_PAIR;
|
||||||
bool permission_denied = false;
|
bool permission_denied = false;
|
||||||
pid_t pid1, pid2, pid3;
|
_cleanup_(pidref_done) PidRef pidref1 = PIDREF_NULL, pidref2 = PIDREF_NULL, pidref3 = PIDREF_NULL;
|
||||||
int r, n = 0;
|
int r, n = 0;
|
||||||
siginfo_t si;
|
siginfo_t si;
|
||||||
|
|
||||||
@ -105,51 +105,48 @@ static void test_shareable_ns(unsigned long nsflag) {
|
|||||||
|
|
||||||
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s));
|
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s));
|
||||||
|
|
||||||
pid1 = fork();
|
r = ASSERT_OK(pidref_safe_fork("(share-ns-1)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref1));
|
||||||
ASSERT_OK_ERRNO(pid1);
|
|
||||||
|
|
||||||
if (pid1 == 0) {
|
if (r == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
if (!ERRNO_IS_PRIVILEGE(r))
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid2 = fork();
|
r = ASSERT_OK(pidref_safe_fork("(share-ns-2)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref2));
|
||||||
ASSERT_OK_ERRNO(pid2);
|
|
||||||
|
|
||||||
if (pid2 == 0) {
|
if (r == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
if (!ERRNO_IS_PRIVILEGE(r))
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid3 = fork();
|
r = ASSERT_OK(pidref_safe_fork("(share-ns-3)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref3));
|
||||||
ASSERT_OK_ERRNO(pid3);
|
|
||||||
|
|
||||||
if (pid3 == 0) {
|
if (r == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
if (!ERRNO_IS_PRIVILEGE(r))
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate(pid1, &si));
|
ASSERT_OK(pidref_wait_for_terminate(&pidref1, &si));
|
||||||
ASSERT_EQ(si.si_code, CLD_EXITED);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
if (si.si_status == EX_NOPERM)
|
if (si.si_status == EX_NOPERM)
|
||||||
permission_denied = true;
|
permission_denied = true;
|
||||||
else
|
else
|
||||||
n += si.si_status;
|
n += si.si_status;
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate(pid2, &si));
|
ASSERT_OK(pidref_wait_for_terminate(&pidref2, &si));
|
||||||
ASSERT_EQ(si.si_code, CLD_EXITED);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
if (si.si_status == EX_NOPERM)
|
if (si.si_status == EX_NOPERM)
|
||||||
permission_denied = true;
|
permission_denied = true;
|
||||||
else
|
else
|
||||||
n += si.si_status;
|
n += si.si_status;
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate(pid3, &si));
|
ASSERT_OK(pidref_wait_for_terminate(&pidref3, &si));
|
||||||
ASSERT_EQ(si.si_code, CLD_EXITED);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
if (si.si_status == EX_NOPERM)
|
if (si.si_status == EX_NOPERM)
|
||||||
permission_denied = true;
|
permission_denied = true;
|
||||||
@ -203,7 +200,6 @@ TEST(protect_kernel_logs) {
|
|||||||
.protect_kernel_logs = true,
|
.protect_kernel_logs = true,
|
||||||
.root_directory_fd = -EBADF,
|
.root_directory_fd = -EBADF,
|
||||||
};
|
};
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (geteuid() > 0) {
|
if (geteuid() > 0) {
|
||||||
@ -224,10 +220,9 @@ TEST(protect_kernel_logs) {
|
|||||||
}
|
}
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
pid = fork();
|
r = ASSERT_OK(safe_fork("(protect)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
|
||||||
ASSERT_OK_ERRNO(pid);
|
|
||||||
|
|
||||||
if (pid == 0) {
|
if (r == 0) {
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC));
|
ASSERT_OK_ERRNO(fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC));
|
||||||
@ -239,8 +234,6 @@ TEST(protect_kernel_logs) {
|
|||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_OK_EQ(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG), EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(idmapping_supported) {
|
TEST(idmapping_supported) {
|
||||||
@ -333,7 +326,7 @@ TEST(process_is_owned_by_uid) {
|
|||||||
ASSERT_OK_ZERO(process_is_owned_by_uid(&pid, getuid()));
|
ASSERT_OK_ZERO(process_is_owned_by_uid(&pid, getuid()));
|
||||||
|
|
||||||
ASSERT_OK(pidref_kill(&pid, SIGKILL));
|
ASSERT_OK(pidref_kill(&pid, SIGKILL));
|
||||||
ASSERT_OK(pidref_wait_for_terminate(&pid, /* ret= */ NULL));
|
ASSERT_OK(pidref_wait_for_terminate(&pid, NULL));
|
||||||
|
|
||||||
/* Test a child that runs in a userns as uid 1, but the userns is owned by us */
|
/* Test a child that runs in a userns as uid 1, but the userns is owned by us */
|
||||||
ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC));
|
ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC));
|
||||||
@ -380,7 +373,7 @@ TEST(process_is_owned_by_uid) {
|
|||||||
ASSERT_OK_POSITIVE(process_is_owned_by_uid(&pid, getuid()));
|
ASSERT_OK_POSITIVE(process_is_owned_by_uid(&pid, getuid()));
|
||||||
|
|
||||||
ASSERT_OK(pidref_kill(&pid, SIGKILL));
|
ASSERT_OK(pidref_kill(&pid, SIGKILL));
|
||||||
ASSERT_OK(pidref_wait_for_terminate(&pid, /* ret= */ NULL));
|
ASSERT_OK(pidref_wait_for_terminate(&pid, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(namespace_get_leader) {
|
TEST(namespace_get_leader) {
|
||||||
|
|||||||
@ -90,8 +90,6 @@ TEST(notify_socket_prepare) {
|
|||||||
_cleanup_free_ char *path = NULL;
|
_cleanup_free_ char *path = NULL;
|
||||||
ASSERT_OK(notify_socket_prepare_full(e, SD_EVENT_PRIORITY_NORMAL - 10, on_recv, &c, true, &path, NULL));
|
ASSERT_OK(notify_socket_prepare_full(e, SD_EVENT_PRIORITY_NORMAL - 10, on_recv, &c, true, &path, NULL));
|
||||||
|
|
||||||
ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
|
|
||||||
|
|
||||||
ASSERT_OK(r = pidref_safe_fork("(test-notify-recv-child)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &c.pidref));
|
ASSERT_OK(r = pidref_safe_fork("(test-notify-recv-child)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &c.pidref));
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
ASSERT_OK_ERRNO(setenv("NOTIFY_SOCKET", path, /* overwrite= */ true));
|
ASSERT_OK_ERRNO(setenv("NOTIFY_SOCKET", path, /* overwrite= */ true));
|
||||||
|
|||||||
@ -464,7 +464,6 @@ TEST(find_executable) {
|
|||||||
static void test_find_executable_exec_one(const char *path) {
|
static void test_find_executable_exec_one(const char *path) {
|
||||||
_cleanup_free_ char *t = NULL;
|
_cleanup_free_ char *t = NULL;
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = find_executable_full(path, NULL, NULL, false, &t, &fd);
|
r = find_executable_full(path, NULL, NULL, false, &t, &fd);
|
||||||
@ -476,15 +475,13 @@ static void test_find_executable_exec_one(const char *path) {
|
|||||||
if (path_is_absolute(path))
|
if (path_is_absolute(path))
|
||||||
ASSERT_STREQ(t, path);
|
ASSERT_STREQ(t, path);
|
||||||
|
|
||||||
pid = fork();
|
r = ASSERT_OK(safe_fork("(find-exec)", FORK_LOG|FORK_DEATHSIG_SIGKILL|FORK_WAIT, /* ret_pid= */ NULL));
|
||||||
assert_se(pid >= 0);
|
|
||||||
if (pid == 0) {
|
if (r == 0) {
|
||||||
r = fexecve_or_execve(fd, t, STRV_MAKE(t, "--version"), STRV_MAKE(NULL));
|
r = fexecve_or_execve(fd, t, STRV_MAKE(t, "--version"), STRV_MAKE(NULL));
|
||||||
log_error_errno(r, "[f]execve: %m");
|
log_error_errno(r, "[f]execve: %m");
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(wait_for_terminate_and_check(t, pid, WAIT_LOG) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(find_executable_exec) {
|
TEST(find_executable_exec) {
|
||||||
|
|||||||
@ -6,25 +6,26 @@
|
|||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
#include "time-util.h"
|
||||||
|
|
||||||
TEST(pidref_is_set) {
|
TEST(pidref_is_set) {
|
||||||
assert_se(!pidref_is_set(NULL));
|
ASSERT_FALSE(pidref_is_set(NULL));
|
||||||
assert_se(!pidref_is_set(&PIDREF_NULL));
|
ASSERT_FALSE(pidref_is_set(&PIDREF_NULL));
|
||||||
assert_se(pidref_is_set(&PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_TRUE(pidref_is_set(&PIDREF_MAKE_FROM_PID(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_equal) {
|
TEST(pidref_equal) {
|
||||||
assert_se(pidref_equal(NULL, NULL));
|
ASSERT_TRUE(pidref_equal(NULL, NULL));
|
||||||
assert_se(pidref_equal(NULL, &PIDREF_NULL));
|
ASSERT_TRUE(pidref_equal(NULL, &PIDREF_NULL));
|
||||||
assert_se(pidref_equal(&PIDREF_NULL, NULL));
|
ASSERT_TRUE(pidref_equal(&PIDREF_NULL, NULL));
|
||||||
assert_se(pidref_equal(&PIDREF_NULL, &PIDREF_NULL));
|
ASSERT_TRUE(pidref_equal(&PIDREF_NULL, &PIDREF_NULL));
|
||||||
|
|
||||||
assert_se(!pidref_equal(NULL, &PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_FALSE(pidref_equal(NULL, &PIDREF_MAKE_FROM_PID(1)));
|
||||||
assert_se(!pidref_equal(&PIDREF_MAKE_FROM_PID(1), NULL));
|
ASSERT_FALSE(pidref_equal(&PIDREF_MAKE_FROM_PID(1), NULL));
|
||||||
assert_se(!pidref_equal(&PIDREF_NULL, &PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_FALSE(pidref_equal(&PIDREF_NULL, &PIDREF_MAKE_FROM_PID(1)));
|
||||||
assert_se(!pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_NULL));
|
ASSERT_FALSE(pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_NULL));
|
||||||
assert_se(pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_TRUE(pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_MAKE_FROM_PID(1)));
|
||||||
assert_se(!pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_MAKE_FROM_PID(2)));
|
ASSERT_FALSE(pidref_equal(&PIDREF_MAKE_FROM_PID(1), &PIDREF_MAKE_FROM_PID(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_set_pid) {
|
TEST(pidref_set_pid) {
|
||||||
@ -34,18 +35,18 @@ TEST(pidref_set_pid) {
|
|||||||
r = pidref_set_pid(&pidref, 1);
|
r = pidref_set_pid(&pidref, 1);
|
||||||
if (r == -ESRCH)
|
if (r == -ESRCH)
|
||||||
return (void) log_tests_skipped_errno(r, "PID1 does not exist");
|
return (void) log_tests_skipped_errno(r, "PID1 does not exist");
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
assert_se(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_TRUE(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(1)));
|
||||||
assert_se(!pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(2)));
|
ASSERT_FALSE(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_set_self) {
|
TEST(pidref_set_self) {
|
||||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
|
||||||
assert_se(pidref_set_self(&pidref) >= 0);
|
ASSERT_OK(pidref_set_self(&pidref));
|
||||||
assert_se(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(getpid_cached())));
|
ASSERT_TRUE(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(getpid_cached())));
|
||||||
assert_se(!pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(getpid_cached()+1)));
|
ASSERT_FALSE(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(getpid_cached()+1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_set_pidstr) {
|
TEST(pidref_set_pidstr) {
|
||||||
@ -53,105 +54,105 @@ TEST(pidref_set_pidstr) {
|
|||||||
char buf[DECIMAL_STR_MAX(pid_t)];
|
char buf[DECIMAL_STR_MAX(pid_t)];
|
||||||
|
|
||||||
xsprintf(buf, PID_FMT, getpid_cached());
|
xsprintf(buf, PID_FMT, getpid_cached());
|
||||||
assert_se(pidref_set_pidstr(&pidref, buf) >= 0);
|
ASSERT_OK(pidref_set_pidstr(&pidref, buf));
|
||||||
assert_se(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(getpid_cached())));
|
ASSERT_TRUE(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(getpid_cached())));
|
||||||
assert_se(!pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(getpid_cached()+1)));
|
ASSERT_FALSE(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(getpid_cached()+1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_set_pidfd) {
|
TEST(pidref_set_pidfd) {
|
||||||
_cleanup_(pidref_done) PidRef a = PIDREF_NULL, b = PIDREF_NULL, c = PIDREF_NULL, d = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef a = PIDREF_NULL, b = PIDREF_NULL, c = PIDREF_NULL, d = PIDREF_NULL;
|
||||||
|
|
||||||
assert_se(pidref_set_self(&a) >= 0);
|
ASSERT_OK(pidref_set_self(&a));
|
||||||
if (a.fd < 0)
|
if (a.fd < 0)
|
||||||
return (void) log_tests_skipped("PIDFD not supported");
|
return (void) log_tests_skipped("PIDFD not supported");
|
||||||
|
|
||||||
assert_se(pidref_set_pidfd(&b, a.fd) >= 0);
|
ASSERT_OK(pidref_set_pidfd(&b, a.fd));
|
||||||
assert_se(pidref_equal(&a, &b));
|
ASSERT_TRUE(pidref_equal(&a, &b));
|
||||||
assert_se(pidref_set_pidfd_take(&c, b.fd) >= 0);
|
ASSERT_OK(pidref_set_pidfd_take(&c, b.fd));
|
||||||
b.fd = -EBADF;
|
b.fd = -EBADF;
|
||||||
assert_se(pidref_equal(&a, &c));
|
ASSERT_TRUE(pidref_equal(&a, &c));
|
||||||
assert_se(pidref_set_pidfd_consume(&d, TAKE_FD(c.fd)) >= 0);
|
ASSERT_OK(pidref_set_pidfd_consume(&d, TAKE_FD(c.fd)));
|
||||||
assert_se(pidref_equal(&a, &d));
|
ASSERT_TRUE(pidref_equal(&a, &d));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_is_self) {
|
TEST(pidref_is_self) {
|
||||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
|
||||||
assert_se(pidref_set_self(&pidref) >= 0);
|
ASSERT_OK(pidref_set_self(&pidref));
|
||||||
assert_se(pidref_is_self(&pidref));
|
ASSERT_TRUE(pidref_is_self(&pidref));
|
||||||
|
|
||||||
assert_se(!pidref_is_self(NULL));
|
ASSERT_FALSE(pidref_is_self(NULL));
|
||||||
assert_se(!pidref_is_self(&PIDREF_NULL));
|
ASSERT_FALSE(pidref_is_self(&PIDREF_NULL));
|
||||||
assert_se(pidref_is_self(&PIDREF_MAKE_FROM_PID(getpid_cached())));
|
ASSERT_TRUE(pidref_is_self(&PIDREF_MAKE_FROM_PID(getpid_cached())));
|
||||||
assert_se(!pidref_is_self(&PIDREF_MAKE_FROM_PID(getpid_cached()+1)));
|
ASSERT_FALSE(pidref_is_self(&PIDREF_MAKE_FROM_PID(getpid_cached()+1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_copy) {
|
TEST(pidref_copy) {
|
||||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_se(pidref_copy(NULL, &pidref) >= 0);
|
ASSERT_OK(pidref_copy(NULL, &pidref));
|
||||||
assert_se(!pidref_is_set(&pidref));
|
ASSERT_FALSE(pidref_is_set(&pidref));
|
||||||
|
|
||||||
assert_se(pidref_copy(&PIDREF_NULL, &pidref) >= 0);
|
ASSERT_OK(pidref_copy(&PIDREF_NULL, &pidref));
|
||||||
assert_se(!pidref_is_set(&pidref));
|
ASSERT_FALSE(pidref_is_set(&pidref));
|
||||||
|
|
||||||
assert_se(pidref_copy(&PIDREF_MAKE_FROM_PID(getpid_cached()), &pidref) >= 0);
|
ASSERT_OK(pidref_copy(&PIDREF_MAKE_FROM_PID(getpid_cached()), &pidref));
|
||||||
assert_se(pidref_is_self(&pidref));
|
ASSERT_TRUE(pidref_is_self(&pidref));
|
||||||
pidref_done(&pidref);
|
pidref_done(&pidref);
|
||||||
|
|
||||||
r = pidref_copy(&PIDREF_MAKE_FROM_PID(1), &pidref);
|
r = pidref_copy(&PIDREF_MAKE_FROM_PID(1), &pidref);
|
||||||
if (r == -ESRCH)
|
if (r == -ESRCH)
|
||||||
return (void) log_tests_skipped_errno(r, "PID1 does not exist");
|
return (void) log_tests_skipped_errno(r, "PID1 does not exist");
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
assert_se(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_TRUE(pidref_equal(&pidref, &PIDREF_MAKE_FROM_PID(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_dup) {
|
TEST(pidref_dup) {
|
||||||
_cleanup_(pidref_freep) PidRef *pidref = NULL;
|
_cleanup_(pidref_freep) PidRef *pidref = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_se(pidref_dup(NULL, &pidref) >= 0);
|
ASSERT_OK(pidref_dup(NULL, &pidref));
|
||||||
assert_se(pidref);
|
ASSERT_NOT_NULL(pidref);
|
||||||
assert_se(!pidref_is_set(pidref));
|
ASSERT_FALSE(pidref_is_set(pidref));
|
||||||
pidref = pidref_free(pidref);
|
pidref = pidref_free(pidref);
|
||||||
|
|
||||||
assert_se(pidref_dup(&PIDREF_NULL, &pidref) >= 0);
|
ASSERT_OK(pidref_dup(&PIDREF_NULL, &pidref));
|
||||||
assert_se(pidref);
|
ASSERT_NOT_NULL(pidref);
|
||||||
assert_se(!pidref_is_set(pidref));
|
ASSERT_FALSE(pidref_is_set(pidref));
|
||||||
pidref = pidref_free(pidref);
|
pidref = pidref_free(pidref);
|
||||||
|
|
||||||
assert_se(pidref_dup(&PIDREF_MAKE_FROM_PID(getpid_cached()), &pidref) >= 0);
|
ASSERT_OK(pidref_dup(&PIDREF_MAKE_FROM_PID(getpid_cached()), &pidref));
|
||||||
assert_se(pidref_is_self(pidref));
|
ASSERT_TRUE(pidref_is_self(pidref));
|
||||||
pidref = pidref_free(pidref);
|
pidref = pidref_free(pidref);
|
||||||
|
|
||||||
r = pidref_dup(&PIDREF_MAKE_FROM_PID(1), &pidref);
|
r = pidref_dup(&PIDREF_MAKE_FROM_PID(1), &pidref);
|
||||||
if (r == -ESRCH)
|
if (r == -ESRCH)
|
||||||
return (void) log_tests_skipped_errno(r, "PID1 does not exist");
|
return (void) log_tests_skipped_errno(r, "PID1 does not exist");
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
assert_se(pidref_equal(pidref, &PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_TRUE(pidref_equal(pidref, &PIDREF_MAKE_FROM_PID(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_new_from_pid) {
|
TEST(pidref_new_from_pid) {
|
||||||
_cleanup_(pidref_freep) PidRef *pidref = NULL;
|
_cleanup_(pidref_freep) PidRef *pidref = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_se(pidref_new_from_pid(-1, &pidref) == -ESRCH);
|
ASSERT_ERROR(pidref_new_from_pid(-1, &pidref), ESRCH);
|
||||||
assert_se(!pidref);
|
ASSERT_NULL(pidref);
|
||||||
|
|
||||||
assert_se(pidref_new_from_pid(0, &pidref) >= 0);
|
ASSERT_OK(pidref_new_from_pid(0, &pidref));
|
||||||
assert_se(pidref_is_self(pidref));
|
ASSERT_TRUE(pidref_is_self(pidref));
|
||||||
pidref = pidref_free(pidref);
|
pidref = pidref_free(pidref);
|
||||||
|
|
||||||
assert_se(pidref_new_from_pid(getpid_cached(), &pidref) >= 0);
|
ASSERT_OK(pidref_new_from_pid(getpid_cached(), &pidref));
|
||||||
assert_se(pidref_is_self(pidref));
|
ASSERT_TRUE(pidref_is_self(pidref));
|
||||||
pidref = pidref_free(pidref);
|
pidref = pidref_free(pidref);
|
||||||
|
|
||||||
r = pidref_new_from_pid(1, &pidref);
|
r = pidref_new_from_pid(1, &pidref);
|
||||||
if (r == -ESRCH)
|
if (r == -ESRCH)
|
||||||
return (void) log_tests_skipped_errno(r, "PID1 does not exist");
|
return (void) log_tests_skipped_errno(r, "PID1 does not exist");
|
||||||
assert_se(r >= 0);
|
ASSERT_OK(r);
|
||||||
assert_se(pidref_equal(pidref, &PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_TRUE(pidref_equal(pidref, &PIDREF_MAKE_FROM_PID(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_kill) {
|
TEST(pidref_kill) {
|
||||||
@ -160,9 +161,9 @@ TEST(pidref_kill) {
|
|||||||
|
|
||||||
ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-kill)", FORK_DEATHSIG_SIGKILL|FORK_FREEZE, &pidref));
|
ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-kill)", FORK_DEATHSIG_SIGKILL|FORK_FREEZE, &pidref));
|
||||||
|
|
||||||
assert_se(pidref_kill(&pidref, SIGKILL) >= 0);
|
ASSERT_OK(pidref_kill(&pidref, SIGKILL));
|
||||||
assert_se(pidref_wait_for_terminate(&pidref, &si) >= 0);
|
ASSERT_OK(pidref_wait_for_terminate(&pidref, &si));
|
||||||
assert_se(si.si_signo == SIGCHLD);
|
ASSERT_EQ(si.si_signo, SIGCHLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_kill_and_sigcont) {
|
TEST(pidref_kill_and_sigcont) {
|
||||||
@ -171,9 +172,9 @@ TEST(pidref_kill_and_sigcont) {
|
|||||||
|
|
||||||
ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-kill-and-sigcont)", FORK_DEATHSIG_SIGTERM|FORK_FREEZE, &pidref));
|
ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-kill-and-sigcont)", FORK_DEATHSIG_SIGTERM|FORK_FREEZE, &pidref));
|
||||||
|
|
||||||
assert_se(pidref_kill_and_sigcont(&pidref, SIGTERM) >= 0);
|
ASSERT_OK(pidref_kill_and_sigcont(&pidref, SIGTERM));
|
||||||
assert_se(pidref_wait_for_terminate(&pidref, &si) >= 0);
|
ASSERT_OK(pidref_wait_for_terminate(&pidref, &si));
|
||||||
assert_se(si.si_signo == SIGCHLD);
|
ASSERT_EQ(si.si_signo, SIGCHLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_sigqueue) {
|
TEST(pidref_sigqueue) {
|
||||||
@ -182,9 +183,9 @@ TEST(pidref_sigqueue) {
|
|||||||
|
|
||||||
ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-sigqueue)", FORK_DEATHSIG_SIGTERM|FORK_FREEZE, &pidref));
|
ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-sigqueue)", FORK_DEATHSIG_SIGTERM|FORK_FREEZE, &pidref));
|
||||||
|
|
||||||
assert_se(pidref_sigqueue(&pidref, SIGTERM, 42) >= 0);
|
ASSERT_OK(pidref_sigqueue(&pidref, SIGTERM, 42));
|
||||||
assert_se(pidref_wait_for_terminate(&pidref, &si) >= 0);
|
ASSERT_OK(pidref_wait_for_terminate(&pidref, &si));
|
||||||
assert_se(si.si_signo == SIGCHLD);
|
ASSERT_EQ(si.si_signo, SIGCHLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_done_sigkill_wait) {
|
TEST(pidref_done_sigkill_wait) {
|
||||||
@ -195,39 +196,41 @@ TEST(pidref_done_sigkill_wait) {
|
|||||||
|
|
||||||
TEST(pidref_verify) {
|
TEST(pidref_verify) {
|
||||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert_se(pidref_verify(NULL) == -ESRCH);
|
ASSERT_ERROR(pidref_verify(NULL), ESRCH);
|
||||||
assert_se(pidref_verify(&PIDREF_NULL) == -ESRCH);
|
ASSERT_ERROR(pidref_verify(&PIDREF_NULL), ESRCH);
|
||||||
|
|
||||||
assert_se(pidref_verify(&PIDREF_MAKE_FROM_PID(1)) == 1);
|
ASSERT_OK_POSITIVE(pidref_verify(&PIDREF_MAKE_FROM_PID(1)));
|
||||||
assert_se(pidref_verify(&PIDREF_MAKE_FROM_PID(getpid_cached())) == 0);
|
ASSERT_OK_ZERO(pidref_verify(&PIDREF_MAKE_FROM_PID(getpid_cached())));
|
||||||
|
|
||||||
assert_se(pidref_set_self(&pidref) >= 0);
|
ASSERT_OK(pidref_set_self(&pidref));
|
||||||
assert_se(pidref_verify(&pidref) == (pidref.fd >= 0));
|
ASSERT_OK(r = pidref_verify(&pidref));
|
||||||
|
ASSERT_EQ(r, (pidref.fd >= 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_is_automatic) {
|
TEST(pidref_is_automatic) {
|
||||||
assert_se(!pidref_is_automatic(NULL));
|
ASSERT_FALSE(pidref_is_automatic(NULL));
|
||||||
assert_se(!pidref_is_automatic(&PIDREF_NULL));
|
ASSERT_FALSE(pidref_is_automatic(&PIDREF_NULL));
|
||||||
assert_se(!pidref_is_automatic(&PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_FALSE(pidref_is_automatic(&PIDREF_MAKE_FROM_PID(1)));
|
||||||
assert_se(!pidref_is_automatic(&PIDREF_MAKE_FROM_PID(getpid_cached())));
|
ASSERT_FALSE(pidref_is_automatic(&PIDREF_MAKE_FROM_PID(getpid_cached())));
|
||||||
assert_se(pidref_is_automatic(&PIDREF_AUTOMATIC));
|
ASSERT_TRUE(pidref_is_automatic(&PIDREF_AUTOMATIC));
|
||||||
|
|
||||||
assert_se(!pid_is_automatic(0));
|
ASSERT_FALSE(pid_is_automatic(0));
|
||||||
assert_se(!pid_is_automatic(1));
|
ASSERT_FALSE(pid_is_automatic(1));
|
||||||
assert_se(!pid_is_automatic(getpid_cached()));
|
ASSERT_FALSE(pid_is_automatic(getpid_cached()));
|
||||||
assert_se(pid_is_automatic(PID_AUTOMATIC));
|
ASSERT_TRUE(pid_is_automatic(PID_AUTOMATIC));
|
||||||
|
|
||||||
assert_se(!pidref_is_set(&PIDREF_AUTOMATIC));
|
ASSERT_FALSE(pidref_is_set(&PIDREF_AUTOMATIC));
|
||||||
assert_se(!pid_is_valid(PID_AUTOMATIC));
|
ASSERT_FALSE(pid_is_valid(PID_AUTOMATIC));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pidref_is_remote) {
|
TEST(pidref_is_remote) {
|
||||||
assert_se(!pidref_is_remote(NULL));
|
ASSERT_FALSE(pidref_is_remote(NULL));
|
||||||
assert_se(!pidref_is_remote(&PIDREF_NULL));
|
ASSERT_FALSE(pidref_is_remote(&PIDREF_NULL));
|
||||||
assert_se(!pidref_is_remote(&PIDREF_MAKE_FROM_PID(1)));
|
ASSERT_FALSE(pidref_is_remote(&PIDREF_MAKE_FROM_PID(1)));
|
||||||
assert_se(!pidref_is_remote(&PIDREF_MAKE_FROM_PID(getpid_cached())));
|
ASSERT_FALSE(pidref_is_remote(&PIDREF_MAKE_FROM_PID(getpid_cached())));
|
||||||
assert_se(!pidref_is_remote(&PIDREF_AUTOMATIC));
|
ASSERT_FALSE(pidref_is_remote(&PIDREF_AUTOMATIC));
|
||||||
|
|
||||||
PidRef p = {
|
PidRef p = {
|
||||||
.pid = 1,
|
.pid = 1,
|
||||||
@ -235,13 +238,31 @@ TEST(pidref_is_remote) {
|
|||||||
.fd_id = 4711,
|
.fd_id = 4711,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_se(pidref_is_set(&p));
|
ASSERT_TRUE(pidref_is_set(&p));
|
||||||
assert_se(pidref_is_remote(&p));
|
ASSERT_TRUE(pidref_is_remote(&p));
|
||||||
assert_se(!pidref_is_automatic(&p));
|
ASSERT_FALSE(pidref_is_automatic(&p));
|
||||||
assert_se(pidref_kill(&p, SIGTERM) == -EREMOTE);
|
ASSERT_ERROR(pidref_kill(&p, SIGTERM), EREMOTE);
|
||||||
assert_se(pidref_kill_and_sigcont(&p, SIGTERM) == -EREMOTE);
|
ASSERT_ERROR(pidref_kill_and_sigcont(&p, SIGTERM), EREMOTE);
|
||||||
assert_se(pidref_wait_for_terminate(&p, /* ret= */ NULL) == -EREMOTE);
|
ASSERT_ERROR(pidref_wait_for_terminate(&p, NULL), EREMOTE);
|
||||||
assert_se(pidref_verify(&p) == -EREMOTE);
|
ASSERT_ERROR(pidref_verify(&p), EREMOTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(pidref_wait_for_terminate_timeout) {
|
||||||
|
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
|
||||||
|
siginfo_t si;
|
||||||
|
|
||||||
|
/* Test successful termination within timeout */
|
||||||
|
ASSERT_OK(pidref_safe_fork("(test-pidref-wait-timeout)", FORK_DEATHSIG_SIGKILL|FORK_FREEZE, &pidref));
|
||||||
|
|
||||||
|
assert_se(pidref_kill(&pidref, SIGKILL) >= 0);
|
||||||
|
ASSERT_OK(pidref_wait_for_terminate_full(&pidref, 5 * USEC_PER_SEC, &si));
|
||||||
|
ASSERT_EQ(si.si_signo, SIGCHLD);
|
||||||
|
|
||||||
|
pidref_done(&pidref);
|
||||||
|
|
||||||
|
/* Test timeout when process doesn't terminate */
|
||||||
|
ASSERT_OK(pidref_safe_fork("(test-pidref-wait-timeout-expired)", FORK_DEATHSIG_SIGKILL|FORK_FREEZE, &pidref));
|
||||||
|
ASSERT_ERROR(pidref_wait_for_terminate_full(&pidref, 100 * USEC_PER_MSEC, NULL), ETIMEDOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||||
|
|||||||
@ -263,7 +263,6 @@ TEST(pid_get_cmdline_harder) {
|
|||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
_cleanup_free_ char *line = NULL;
|
_cleanup_free_ char *line = NULL;
|
||||||
_cleanup_strv_free_ char **args = NULL;
|
_cleanup_strv_free_ char **args = NULL;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (geteuid() != 0) {
|
if (geteuid() != 0) {
|
||||||
@ -286,297 +285,286 @@ TEST(pid_get_cmdline_harder) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pid = fork();
|
r = ASSERT_OK(safe_fork("(cmdline)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
|
||||||
if (pid > 0) {
|
if (r == 0) {
|
||||||
siginfo_t si;
|
r = detach_mount_namespace();
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "detach mount namespace failed: %m");
|
||||||
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
|
ASSERT_OK(r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
(void) wait_for_terminate(pid, &si);
|
fd = mkostemp(path, O_CLOEXEC);
|
||||||
|
ASSERT_OK_ERRNO(fd);
|
||||||
|
|
||||||
ASSERT_EQ(si.si_code, CLD_EXITED);
|
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
|
||||||
ASSERT_OK_ZERO(si.si_status);
|
* will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
|
||||||
|
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
|
||||||
|
/* This happens under selinux… Abort the test in this case. */
|
||||||
|
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
|
||||||
|
ASSERT_TRUE(IN_SET(errno, EPERM, EACCES));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
/* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read
|
||||||
}
|
* the cmdline. */
|
||||||
|
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
|
||||||
|
log_warning("Testing without RLIMIT_STACK=infinity");
|
||||||
|
|
||||||
ASSERT_OK_ZERO(pid);
|
ASSERT_OK_ERRNO(unlink(path));
|
||||||
|
|
||||||
r = detach_mount_namespace();
|
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
|
||||||
if (r < 0) {
|
|
||||||
log_warning_errno(r, "detach mount namespace failed: %m");
|
|
||||||
if (!ERRNO_IS_PRIVILEGE(r))
|
|
||||||
ASSERT_OK(r);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = mkostemp(path, O_CLOEXEC);
|
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
|
||||||
ASSERT_OK_ERRNO(fd);
|
|
||||||
|
|
||||||
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
* will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
|
log_debug("'%s'", line);
|
||||||
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
|
ASSERT_STREQ(line, "[testa]");
|
||||||
/* This happens under selinux… Abort the test in this case. */
|
line = mfree(line);
|
||||||
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
|
|
||||||
ASSERT_TRUE(IN_SET(errno, EPERM, EACCES));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line));
|
||||||
* the cmdline. */
|
log_debug("'%s'", line);
|
||||||
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
|
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
|
||||||
log_warning("Testing without RLIMIT_STACK=infinity");
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(unlink(path));
|
ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
|
log_debug("'%s'", line);
|
||||||
|
ASSERT_STREQ(line, "");
|
||||||
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
|
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
|
ASSERT_STREQ(line, "…");
|
||||||
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
|
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
|
ASSERT_STREQ(line, "[…");
|
||||||
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
ASSERT_STREQ(line, "[t…");
|
||||||
ASSERT_STREQ(line, "[testa]");
|
line = mfree(line);
|
||||||
line = mfree(line);
|
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line));
|
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
ASSERT_STREQ(line, "[te…");
|
||||||
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
|
line = mfree(line);
|
||||||
line = mfree(line);
|
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
ASSERT_STREQ(line, "[tes…");
|
||||||
ASSERT_STREQ(line, "");
|
line = mfree(line);
|
||||||
line = mfree(line);
|
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "…");
|
ASSERT_STREQ(line, "[test…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[…");
|
ASSERT_STREQ(line, "[testa]");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "[t…");
|
ASSERT_STREQ(line, "[testa]");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
||||||
ASSERT_STREQ(line, "[te…");
|
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]")));
|
||||||
line = mfree(line);
|
args = strv_free(args);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
|
||||||
ASSERT_STREQ(line, "[tes…");
|
|
||||||
line = mfree(line);
|
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
|
||||||
ASSERT_STREQ(line, "[test…");
|
|
||||||
line = mfree(line);
|
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
|
||||||
ASSERT_STREQ(line, "[testa]");
|
|
||||||
line = mfree(line);
|
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
|
||||||
ASSERT_STREQ(line, "[testa]");
|
|
||||||
line = mfree(line);
|
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
|
||||||
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]")));
|
|
||||||
args = strv_free(args);
|
|
||||||
|
|
||||||
/* Test with multiple arguments that don't require quoting */
|
/* Test with multiple arguments that don't require quoting */
|
||||||
|
|
||||||
ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8);
|
ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar");
|
ASSERT_STREQ(line, "foo bar");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
ASSERT_STREQ(line, "foo bar");
|
ASSERT_STREQ(line, "foo bar");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
||||||
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar")));
|
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar")));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4);
|
ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4);
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "…");
|
ASSERT_STREQ(line, "…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "f…");
|
ASSERT_STREQ(line, "f…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "fo…");
|
ASSERT_STREQ(line, "fo…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo…");
|
ASSERT_STREQ(line, "foo…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo …");
|
ASSERT_STREQ(line, "foo …");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo b…");
|
ASSERT_STREQ(line, "foo b…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo ba…");
|
ASSERT_STREQ(line, "foo ba…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar…");
|
ASSERT_STREQ(line, "foo bar…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar …");
|
ASSERT_STREQ(line, "foo bar …");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar q…");
|
ASSERT_STREQ(line, "foo bar q…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar qu…");
|
ASSERT_STREQ(line, "foo bar qu…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "foo bar quux");
|
ASSERT_STREQ(line, "foo bar quux");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
||||||
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
|
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(ftruncate(fd, 0));
|
ASSERT_OK_ERRNO(ftruncate(fd, 0));
|
||||||
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
|
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
|
||||||
|
|
||||||
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
|
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
|
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[aaaa bbb…");
|
ASSERT_STREQ(line, "[aaaa bbb…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[aaaa bbbb…");
|
ASSERT_STREQ(line, "[aaaa bbbb…");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
|
||||||
log_debug("'%s'", line);
|
log_debug("'%s'", line);
|
||||||
ASSERT_STREQ(line, "[aaaa bbbb …");
|
ASSERT_STREQ(line, "[aaaa bbbb …");
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
|
||||||
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
|
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
/* Test with multiple arguments that do require quoting */
|
/* Test with multiple arguments that do require quoting */
|
||||||
|
|
||||||
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
|
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
|
||||||
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\""
|
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\""
|
||||||
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
|
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
|
||||||
#define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``")
|
#define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``")
|
||||||
|
|
||||||
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
|
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
|
||||||
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1));
|
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1));
|
||||||
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1)));
|
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1)));
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
|
||||||
log_debug("got: ==%s==", line);
|
log_debug("got: ==%s==", line);
|
||||||
log_debug("exp: ==%s==", EXPECT1);
|
log_debug("exp: ==%s==", EXPECT1);
|
||||||
ASSERT_STREQ(line, EXPECT1);
|
ASSERT_STREQ(line, EXPECT1);
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
|
||||||
log_debug("got: ==%s==", line);
|
log_debug("got: ==%s==", line);
|
||||||
log_debug("exp: ==%s==", EXPECT1p);
|
log_debug("exp: ==%s==", EXPECT1p);
|
||||||
ASSERT_STREQ(line, EXPECT1p);
|
ASSERT_STREQ(line, EXPECT1p);
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
|
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
|
||||||
ASSERT_TRUE(strv_equal(args, EXPECT1v));
|
ASSERT_TRUE(strv_equal(args, EXPECT1v));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
#define CMDLINE2 "foo\0\1\2\3\0\0"
|
#define CMDLINE2 "foo\0\1\2\3\0\0"
|
||||||
#define EXPECT2 "foo \"\\001\\002\\003\""
|
#define EXPECT2 "foo \"\\001\\002\\003\""
|
||||||
#define EXPECT2p "foo $'\\001\\002\\003'"
|
#define EXPECT2p "foo $'\\001\\002\\003'"
|
||||||
#define EXPECT2v STRV_MAKE("foo", "\1\2\3")
|
#define EXPECT2v STRV_MAKE("foo", "\1\2\3")
|
||||||
|
|
||||||
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
|
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
|
||||||
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2));
|
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2));
|
||||||
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2));
|
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2));
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
|
||||||
log_debug("got: ==%s==", line);
|
log_debug("got: ==%s==", line);
|
||||||
log_debug("exp: ==%s==", EXPECT2);
|
log_debug("exp: ==%s==", EXPECT2);
|
||||||
ASSERT_STREQ(line, EXPECT2);
|
ASSERT_STREQ(line, EXPECT2);
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
|
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
|
||||||
log_debug("got: ==%s==", line);
|
log_debug("got: ==%s==", line);
|
||||||
log_debug("exp: ==%s==", EXPECT2p);
|
log_debug("exp: ==%s==", EXPECT2p);
|
||||||
ASSERT_STREQ(line, EXPECT2p);
|
ASSERT_STREQ(line, EXPECT2p);
|
||||||
line = mfree(line);
|
line = mfree(line);
|
||||||
|
|
||||||
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
|
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
|
||||||
ASSERT_TRUE(strv_equal(args, EXPECT2v));
|
ASSERT_TRUE(strv_equal(args, EXPECT2v));
|
||||||
args = strv_free(args);
|
args = strv_free(args);
|
||||||
|
|
||||||
safe_close(fd);
|
safe_close(fd);
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(getpid_cached) {
|
TEST(getpid_cached) {
|
||||||
siginfo_t si;
|
pid_t a, b, c, d, e, f;
|
||||||
pid_t a, b, c, d, e, f, child;
|
int r;
|
||||||
|
|
||||||
a = getpid();
|
a = getpid();
|
||||||
b = getpid_cached();
|
b = getpid_cached();
|
||||||
@ -585,10 +573,9 @@ TEST(getpid_cached) {
|
|||||||
ASSERT_EQ(a, b);
|
ASSERT_EQ(a, b);
|
||||||
ASSERT_EQ(a, c);
|
ASSERT_EQ(a, c);
|
||||||
|
|
||||||
child = fork();
|
r = ASSERT_OK(safe_fork("(getpid)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
|
||||||
ASSERT_OK_ERRNO(child);
|
|
||||||
|
|
||||||
if (child == 0) {
|
if (r == 0) {
|
||||||
/* In child */
|
/* In child */
|
||||||
a = getpid();
|
a = getpid();
|
||||||
b = getpid_cached();
|
b = getpid_cached();
|
||||||
@ -606,10 +593,6 @@ TEST(getpid_cached) {
|
|||||||
ASSERT_EQ(a, d);
|
ASSERT_EQ(a, d);
|
||||||
ASSERT_EQ(a, e);
|
ASSERT_EQ(a, e);
|
||||||
ASSERT_EQ(a, f);
|
ASSERT_EQ(a, f);
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate(child, &si));
|
|
||||||
ASSERT_EQ(si.si_status, 0);
|
|
||||||
ASSERT_EQ(si.si_code, CLD_EXITED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(getpid_measure) {
|
TEST(getpid_measure) {
|
||||||
@ -641,8 +624,6 @@ TEST(safe_fork) {
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
BLOCK_SIGNALS(SIGCHLD);
|
|
||||||
|
|
||||||
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
|
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
|
|
||||||
@ -653,11 +634,14 @@ TEST(safe_fork) {
|
|||||||
_exit(88);
|
_exit(88);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate(pid, &status));
|
_cleanup_(pidref_done) PidRef child = PIDREF_NULL;
|
||||||
|
ASSERT_OK(pidref_set_pid(&child, pid));
|
||||||
|
|
||||||
|
ASSERT_OK(pidref_wait_for_terminate(&child, &status));
|
||||||
ASSERT_EQ(status.si_code, CLD_EXITED);
|
ASSERT_EQ(status.si_code, CLD_EXITED);
|
||||||
ASSERT_EQ(status.si_status, 88);
|
ASSERT_EQ(status.si_status, 88);
|
||||||
|
|
||||||
_cleanup_(pidref_done) PidRef child = PIDREF_NULL;
|
pidref_done(&child);
|
||||||
r = pidref_safe_fork("(test-child)", FORK_DETACH, &child);
|
r = pidref_safe_fork("(test-child)", FORK_DETACH, &child);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
/* Don't freeze so this doesn't linger around forever in case something goes wrong. */
|
/* Don't freeze so this doesn't linger around forever in case something goes wrong. */
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
|
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
|
||||||
_cleanup_(manager_freep) Manager *m = NULL;
|
_cleanup_(manager_freep) Manager *m = NULL;
|
||||||
Unit *idle_ok, *idle_bad, *rr_ok, *rr_bad, *rr_sched;
|
Unit *idle_ok, *idle_bad, *rr_ok, *rr_bad, *rr_sched, *ext_ok;
|
||||||
Service *ser;
|
Service *ser;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -76,5 +76,11 @@ int main(int argc, char *argv[]) {
|
|||||||
assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
|
assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR);
|
||||||
assert_se(ser->exec_context.cpu_sched_priority == 99);
|
assert_se(ser->exec_context.cpu_sched_priority == 99);
|
||||||
|
|
||||||
|
/* load ext ok */
|
||||||
|
assert_se(manager_load_startable_unit_or_warn(m, "sched_ext_ok.service", NULL, &ext_ok) >= 0);
|
||||||
|
ser = SERVICE(ext_ok);
|
||||||
|
assert_se(ser->exec_context.cpu_sched_policy == SCHED_EXT);
|
||||||
|
assert_se(ser->exec_context.cpu_sched_priority == 0);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -143,7 +143,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
|
|
||||||
assert_se(event = udev_event_new(dev, NULL, EVENT_TEST_RULE_RUNNER));
|
assert_se(event = udev_event_new(dev, NULL, EVENT_TEST_RULE_RUNNER));
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD) >= 0);
|
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP) >= 0);
|
||||||
|
|
||||||
/* do what devtmpfs usually provides us */
|
/* do what devtmpfs usually provides us */
|
||||||
if (sd_device_get_devname(dev, &devname) >= 0) {
|
if (sd_device_get_devname(dev, &devname) >= 0) {
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "mountpoint-util.h"
|
#include "mountpoint-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "signal-util.h"
|
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
@ -104,8 +103,6 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
test_setup_logging(LOG_DEBUG);
|
test_setup_logging(LOG_DEBUG);
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
test_event_spawn_cat(true, SIZE_MAX);
|
test_event_spawn_cat(true, SIZE_MAX);
|
||||||
test_event_spawn_cat(false, SIZE_MAX);
|
test_event_spawn_cat(false, SIZE_MAX);
|
||||||
test_event_spawn_cat(true, 5);
|
test_event_spawn_cat(true, 5);
|
||||||
|
|||||||
@ -390,7 +390,7 @@ void manager_revert(Manager *manager) {
|
|||||||
manager_kill_workers(manager, SIGTERM);
|
manager_kill_workers(manager, SIGTERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
static int on_worker_exit(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
||||||
_cleanup_(worker_freep) Worker *worker = ASSERT_PTR(userdata);
|
_cleanup_(worker_freep) Worker *worker = ASSERT_PTR(userdata);
|
||||||
sd_device *dev = worker->event ? ASSERT_PTR(worker->event->dev) : NULL;
|
sd_device *dev = worker->event ? ASSERT_PTR(worker->event->dev) : NULL;
|
||||||
|
|
||||||
@ -452,11 +452,11 @@ static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = event_add_child_pidref(manager->event, &worker->child_event_source, &worker->pidref, WEXITED, on_sigchld, worker);
|
r = event_add_child_pidref(manager->event, &worker->child_event_source, &worker->pidref, WEXITED, on_worker_exit, worker);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_event_source_set_priority(worker->child_event_source, EVENT_PRIORITY_WORKER_SIGCHLD);
|
r = sd_event_source_set_priority(worker->child_event_source, EVENT_PRIORITY_WORKER_EXIT);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1363,9 +1363,6 @@ static int manager_setup_event(Manager *manager) {
|
|||||||
|
|
||||||
assert(manager);
|
assert(manager);
|
||||||
|
|
||||||
/* block SIGCHLD for listening child events. */
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = sd_event_default(&e);
|
r = sd_event_default(&e);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate event loop: %m");
|
return log_error_errno(r, "Failed to allocate event loop: %m");
|
||||||
|
|||||||
@ -17,13 +17,13 @@
|
|||||||
/* This must have a higher priority than the worker notification, to make IN_IGNORED event received earlier
|
/* This must have a higher priority than the worker notification, to make IN_IGNORED event received earlier
|
||||||
* than notifications about requests of adding/removing inotify watches. */
|
* than notifications about requests of adding/removing inotify watches. */
|
||||||
#define EVENT_PRIORITY_INOTIFY_WATCH (SD_EVENT_PRIORITY_NORMAL - 4)
|
#define EVENT_PRIORITY_INOTIFY_WATCH (SD_EVENT_PRIORITY_NORMAL - 4)
|
||||||
/* This must have a higher priority than the worker SIGCHLD event, to make notifications about completions of
|
/* This must have a higher priority than the worker exit event, to make notifications about completions of
|
||||||
* processing events received before SIGCHLD. */
|
* processing events received before exit. */
|
||||||
#define EVENT_PRIORITY_WORKER_NOTIFY (SD_EVENT_PRIORITY_NORMAL - 3)
|
#define EVENT_PRIORITY_WORKER_NOTIFY (SD_EVENT_PRIORITY_NORMAL - 3)
|
||||||
/* This should have a higher priority than timer events about killing long running worker processes or idle
|
/* This should have a higher priority than timer events about killing long running worker processes or idle
|
||||||
* worker processes. */
|
* worker processes. */
|
||||||
#define EVENT_PRIORITY_WORKER_SIGCHLD (SD_EVENT_PRIORITY_NORMAL - 2)
|
#define EVENT_PRIORITY_WORKER_EXIT (SD_EVENT_PRIORITY_NORMAL - 2)
|
||||||
/* As said in the above, this should have a lower proority than the SIGCHLD event source. */
|
/* As said in the above, this should have a lower proority than the exit event source. */
|
||||||
#define EVENT_PRIORITY_WORKER_TIMER (SD_EVENT_PRIORITY_NORMAL - 1)
|
#define EVENT_PRIORITY_WORKER_TIMER (SD_EVENT_PRIORITY_NORMAL - 1)
|
||||||
/* This should have a lower priority than most event sources, but let's process earlier than varlink and the
|
/* This should have a lower priority than most event sources, but let's process earlier than varlink and the
|
||||||
* legacy control socket. */
|
* legacy control socket. */
|
||||||
|
|||||||
@ -146,7 +146,7 @@ static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *use
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
static int on_spawn_exit(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
||||||
Spawn *spawn = ASSERT_PTR(userdata);
|
Spawn *spawn = ASSERT_PTR(userdata);
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userd
|
|||||||
|
|
||||||
static int spawn_wait(Spawn *spawn) {
|
static int spawn_wait(Spawn *spawn) {
|
||||||
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
||||||
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *sigchld_source = NULL;
|
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *child_source = NULL;
|
||||||
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *stdout_source = NULL;
|
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *stdout_source = NULL;
|
||||||
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *stderr_source = NULL;
|
_cleanup_(sd_event_source_disable_unrefp) sd_event_source *stderr_source = NULL;
|
||||||
int r;
|
int r;
|
||||||
@ -214,11 +214,12 @@ static int spawn_wait(Spawn *spawn) {
|
|||||||
return log_device_debug_errno(spawn->device, r, "Failed to create stderr event source: %m");
|
return log_device_debug_errno(spawn->device, r, "Failed to create stderr event source: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
r = event_add_child_pidref(e, &sigchld_source, &spawn->pidref, WEXITED, on_spawn_sigchld, spawn);
|
r = event_add_child_pidref(e, &child_source, &spawn->pidref, WEXITED, on_spawn_exit, spawn);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_debug_errno(spawn->device, r, "Failed to create sigchild event source: %m");
|
return log_device_debug_errno(spawn->device, r, "Failed to create sigchild event source: %m");
|
||||||
/* SIGCHLD should be processed after IO is complete */
|
|
||||||
r = sd_event_source_set_priority(sigchld_source, SD_EVENT_PRIORITY_NORMAL + 1);
|
/* Child exit should be processed after IO is complete */
|
||||||
|
r = sd_event_source_set_priority(child_source, SD_EVENT_PRIORITY_NORMAL + 1);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_debug_errno(spawn->device, r, "Failed to set priority to sigchild event source: %m");
|
return log_device_debug_errno(spawn->device, r, "Failed to set priority to sigchild event source: %m");
|
||||||
|
|
||||||
|
|||||||
@ -48,7 +48,7 @@ static int on_worker_exit(sd_event_source *s, const siginfo_t *si, void *userdat
|
|||||||
else if (si->si_code == CLD_DUMPED)
|
else if (si->si_code == CLD_DUMPED)
|
||||||
log_warning("Worker " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
|
log_warning("Worker " PID_FMT " dumped core by signal %s, ignoring.", si->si_pid, signal_to_string(si->si_status));
|
||||||
else
|
else
|
||||||
log_warning("Can't handle SIGCHLD of this type");
|
log_warning("Can't handle exit code of this type");
|
||||||
|
|
||||||
(void) start_workers(m, /* explicit_request= */ false); /* Fill up workers again if we fell below the low watermark */
|
(void) start_workers(m, /* explicit_request= */ false); /* Fill up workers again if we fell below the low watermark */
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
#include "daemon-util.h"
|
#include "daemon-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "signal-util.h"
|
|
||||||
#include "userdbd-manager.h"
|
#include "userdbd-manager.h"
|
||||||
|
|
||||||
/* This service offers two Varlink services, both implementing io.systemd.UserDatabase:
|
/* This service offers two Varlink services, both implementing io.systemd.UserDatabase:
|
||||||
@ -39,8 +38,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (setenv("SYSTEMD_BYPASS_USERDB", "io.systemd.NameServiceSwitch:io.systemd.Multiplexer:io.systemd.DropIn", 1) < 0)
|
if (setenv("SYSTEMD_BYPASS_USERDB", "io.systemd.NameServiceSwitch:io.systemd.Multiplexer:io.systemd.DropIn", 1) < 0)
|
||||||
return log_error_errno(errno, "Failed to set $SYSTEMD_BYPASS_USERDB: %m");
|
return log_error_errno(errno, "Failed to set $SYSTEMD_BYPASS_USERDB: %m");
|
||||||
|
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0);
|
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Could not create manager: %m");
|
return log_error_errno(r, "Could not create manager: %m");
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "locale-util.h"
|
#include "locale-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
|
#include "pidref.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
@ -255,7 +256,6 @@ assert_cc(STRLEN(SYSTEMD_DEFAULT_KEYMAP) > 0);
|
|||||||
static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
|
static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
|
||||||
const char* args[8];
|
const char* args[8];
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(vc);
|
assert(vc);
|
||||||
@ -286,7 +286,8 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
|
|||||||
log_debug("Executing \"%s\"...", strnull(cmd));
|
log_debug("Executing \"%s\"...", strnull(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -294,13 +295,12 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wait_for_terminate_and_check(KBD_LOADKEYS, pid, WAIT_LOG);
|
return pidref_wait_for_terminate_and_check(KBD_LOADKEYS, &pidref, WAIT_LOG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int font_load_and_wait(const char *vc, Context *c) {
|
static int font_load_and_wait(const char *vc, Context *c) {
|
||||||
const char* args[9];
|
const char* args[9];
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
pid_t pid;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(vc);
|
assert(vc);
|
||||||
@ -337,7 +337,8 @@ static int font_load_and_wait(const char *vc, Context *c) {
|
|||||||
log_debug("Executing \"%s\"...", strnull(cmd));
|
log_debug("Executing \"%s\"...", strnull(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
|
r = pidref_safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -348,7 +349,7 @@ static int font_load_and_wait(const char *vc, Context *c) {
|
|||||||
/* setfont returns EX_OSERR when ioctl(KDFONTOP/PIO_FONTX/PIO_FONTX) fails. This might mean various
|
/* setfont returns EX_OSERR when ioctl(KDFONTOP/PIO_FONTX/PIO_FONTX) fails. This might mean various
|
||||||
* things, but in particular lack of a graphical console. Let's be generous and not treat this as an
|
* things, but in particular lack of a graphical console. Let's be generous and not treat this as an
|
||||||
* error. */
|
* error. */
|
||||||
r = wait_for_terminate_and_check(KBD_SETFONT, pid, WAIT_LOG_ABNORMAL);
|
r = pidref_wait_for_terminate_and_check(KBD_SETFONT, &pidref, WAIT_LOG_ABNORMAL);
|
||||||
if (r == EX_OSERR)
|
if (r == EX_OSERR)
|
||||||
log_notice(KBD_SETFONT " failed with a \"system error\" (EX_OSERR), ignoring.");
|
log_notice(KBD_SETFONT " failed with a \"system error\" (EX_OSERR), ignoring.");
|
||||||
else if (r >= 0 && r != EXIT_SUCCESS)
|
else if (r >= 0 && r != EXIT_SUCCESS)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user