mirror of
https://github.com/systemd/systemd
synced 2024-07-24 03:36:24 +00:00
Merge pull request #29152 from poettering/pidref-more
pid1: port more code over to PidRef (i.e. pidfd based operation)
This commit is contained in:
commit
498ef07dd8
7
TODO
7
TODO
|
@ -174,14 +174,9 @@ Features:
|
|||
- pid_is_unwaited() → pidref_is_unwaited()
|
||||
- pid_is_alive() → pidref_is_alive()
|
||||
- unit_watch_pid() → unit_watch_pidref()
|
||||
- unit_kill_common()
|
||||
- unit_kill_context()
|
||||
- service_set_main_pid()
|
||||
- actually wait for POLLIN on piref's pidfd in service logic
|
||||
- unit_main_pid() + unit_control_pid()
|
||||
- actually wait for POLLIN on pidref's pidfd in service logic
|
||||
- exec_spawn()
|
||||
- serialization of control/main pid in service, socket, mount, swap units
|
||||
- unit_fork_and_watch_rm_rf()
|
||||
- cg_pid_get_unit()
|
||||
- openpt_allocate_in_namespace()
|
||||
- scope dbus PIDs property needs to gain PIDFDs companion
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "parse-util.h"
|
||||
#include "pidref.h"
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
|
||||
int pidref_set_pid(PidRef *pidref, pid_t pid) {
|
||||
int fd;
|
||||
|
@ -143,3 +144,30 @@ int pidref_kill_and_sigcont(PidRef *pidref, int sig) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pidref_sigqueue(PidRef *pidref, int sig, int value) {
|
||||
|
||||
if (!pidref)
|
||||
return -ESRCH;
|
||||
|
||||
if (pidref->fd >= 0) {
|
||||
siginfo_t si;
|
||||
|
||||
/* We can't use structured initialization here, since the structure contains various unions
|
||||
* and these fields lie in overlapping (carefully aligned) unions that LLVM is allergic to
|
||||
* allow assignments to */
|
||||
zero(si);
|
||||
si.si_signo = sig;
|
||||
si.si_code = SI_QUEUE;
|
||||
si.si_pid = getpid_cached();
|
||||
si.si_uid = getuid();
|
||||
si.si_value.sival_int = value;
|
||||
|
||||
return RET_NERRNO(pidfd_send_signal(pidref->fd, sig, &si, 0));
|
||||
}
|
||||
|
||||
if (pidref->pid > 0)
|
||||
return RET_NERRNO(sigqueue(pidref->pid, sig, (const union sigval) { .sival_int = value }));
|
||||
|
||||
return -ESRCH;
|
||||
}
|
||||
|
|
|
@ -25,5 +25,6 @@ void pidref_done(PidRef *pidref);
|
|||
|
||||
int pidref_kill(PidRef *pidref, int sig);
|
||||
int pidref_kill_and_sigcont(PidRef *pidref, int sig);
|
||||
int pidref_sigqueue(PidRef *pidfref, int sig, int value);
|
||||
|
||||
#define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
|
||||
|
|
|
@ -134,7 +134,6 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
|
|||
int read_only, make_file_or_directory;
|
||||
Unit *u = ASSERT_PTR(userdata);
|
||||
ExecContext *c;
|
||||
pid_t unit_pid;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
@ -192,14 +191,14 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
|
|||
if (!exec_needs_mount_namespace(c, NULL, unit_get_exec_runtime(u)))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit not running in private mount namespace, cannot activate bind mount");
|
||||
|
||||
unit_pid = unit_main_pid(u);
|
||||
if (unit_pid == 0 || !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
|
||||
PidRef* unit_pid = unit_main_pid(u);
|
||||
if (!pidref_is_set(unit_pid) || !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not running");
|
||||
|
||||
propagate_directory = strjoina("/run/systemd/propagate/", u->id);
|
||||
if (is_image)
|
||||
r = mount_image_in_namespace(
|
||||
unit_pid,
|
||||
unit_pid->pid,
|
||||
propagate_directory,
|
||||
"/run/systemd/incoming/",
|
||||
src, dest,
|
||||
|
@ -209,7 +208,7 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
|
|||
c->mount_image_policy ?: &image_policy_service);
|
||||
else
|
||||
r = bind_mount_in_namespace(
|
||||
unit_pid,
|
||||
unit_pid->pid,
|
||||
propagate_directory,
|
||||
"/run/systemd/incoming/",
|
||||
src, dest,
|
||||
|
|
|
@ -1331,7 +1331,6 @@ int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bu
|
|||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_set_free_ Set *pids = NULL;
|
||||
Unit *u = userdata;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
@ -1359,16 +1358,16 @@ int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bu
|
|||
}
|
||||
|
||||
/* The main and control pids might live outside of the cgroup, hence fetch them separately */
|
||||
pid = unit_main_pid(u);
|
||||
if (pid > 0) {
|
||||
r = append_process(reply, NULL, pid, pids);
|
||||
PidRef *pid = unit_main_pid(u);
|
||||
if (pidref_is_set(pid)) {
|
||||
r = append_process(reply, NULL, pid->pid, pids);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
pid = unit_control_pid(u);
|
||||
if (pid > 0) {
|
||||
r = append_process(reply, NULL, pid, pids);
|
||||
if (pidref_is_set(pid)) {
|
||||
r = append_process(reply, NULL, pid->pid, pids);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -1036,9 +1036,9 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
|
|||
UNIT(m),
|
||||
&m->kill_context,
|
||||
state_to_kill_operation(state),
|
||||
-1,
|
||||
m->control_pid.pid,
|
||||
false);
|
||||
/* main_pid= */ NULL,
|
||||
&m->control_pid,
|
||||
/* main_pid_alien= */ false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -2213,26 +2213,13 @@ static void mount_reset_failed(Unit *u) {
|
|||
m->clean_result = MOUNT_SUCCESS;
|
||||
}
|
||||
|
||||
static int mount_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
|
||||
Mount *m = MOUNT(u);
|
||||
|
||||
assert(m);
|
||||
|
||||
return unit_kill_common(u, who, signo, code, value, -1, m->control_pid.pid, error);
|
||||
}
|
||||
|
||||
static int mount_control_pid(Unit *u) {
|
||||
Mount *m = MOUNT(u);
|
||||
|
||||
assert(m);
|
||||
|
||||
return m->control_pid.pid;
|
||||
static PidRef* mount_control_pid(Unit *u) {
|
||||
return &ASSERT_PTR(MOUNT(u))->control_pid;
|
||||
}
|
||||
|
||||
static int mount_clean(Unit *u, ExecCleanMask mask) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
Mount *m = MOUNT(u);
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
@ -2257,11 +2244,7 @@ static int mount_clean(Unit *u, ExecCleanMask mask) {
|
|||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = unit_fork_and_watch_rm_rf(u, l, &pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = pidref_set_pid(&m->control_pid, pid);
|
||||
r = unit_fork_and_watch_rm_rf(u, l, &m->control_pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -2358,7 +2341,6 @@ const UnitVTable mount_vtable = {
|
|||
.stop = mount_stop,
|
||||
.reload = mount_reload,
|
||||
|
||||
.kill = mount_kill,
|
||||
.clean = mount_clean,
|
||||
.can_clean = mount_can_clean,
|
||||
|
||||
|
|
|
@ -345,7 +345,9 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
|
|||
state != SCOPE_STOP_SIGTERM ? KILL_KILL :
|
||||
s->was_abandoned ? KILL_TERMINATE_AND_LOG :
|
||||
KILL_TERMINATE,
|
||||
-1, -1, false);
|
||||
/* main_pid= */ NULL,
|
||||
/* control_pid= */ NULL,
|
||||
/* main_pid_alien= */ false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
@ -370,8 +372,8 @@ fail:
|
|||
}
|
||||
|
||||
static int scope_enter_start_chown(Scope *s) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
Unit *u = UNIT(s);
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
@ -381,7 +383,7 @@ static int scope_enter_start_chown(Scope *s) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_fork_helper_process(u, "(sd-chown-cgroup)", &pid);
|
||||
r = unit_fork_helper_process(u, "(sd-chown-cgroup)", &pidref);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -418,7 +420,7 @@ static int scope_enter_start_chown(Scope *s) {
|
|||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
r = unit_watch_pid(UNIT(s), pid, true);
|
||||
r = unit_watch_pid(UNIT(s), pidref.pid, /* exclusive= */ true);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -531,10 +533,6 @@ static void scope_reset_failed(Unit *u) {
|
|||
s->result = SCOPE_SUCCESS;
|
||||
}
|
||||
|
||||
static int scope_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
|
||||
return unit_kill_common(u, who, signo, code, value, -1, -1, error);
|
||||
}
|
||||
|
||||
static int scope_get_timeout(Unit *u, usec_t *timeout) {
|
||||
Scope *s = SCOPE(u);
|
||||
usec_t t;
|
||||
|
@ -828,8 +826,6 @@ const UnitVTable scope_vtable = {
|
|||
.start = scope_start,
|
||||
.stop = scope_stop,
|
||||
|
||||
.kill = scope_kill,
|
||||
|
||||
.freeze = unit_freeze_vtable_common,
|
||||
.thaw = unit_thaw_vtable_common,
|
||||
|
||||
|
|
|
@ -179,38 +179,51 @@ static void service_unwatch_pid_file(Service *s) {
|
|||
s->pid_file_pathspec = mfree(s->pid_file_pathspec);
|
||||
}
|
||||
|
||||
static int service_set_main_pidref(Service *s, PidRef *pidref) {
|
||||
assert(s);
|
||||
|
||||
/* Takes ownership of the specified pidref on success, but not on failure. */
|
||||
|
||||
if (!pidref_is_set(pidref))
|
||||
return -ESRCH;
|
||||
|
||||
if (pidref->pid <= 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (pidref->pid == getpid_cached())
|
||||
return -EINVAL;
|
||||
|
||||
if (s->main_pid.pid == pidref->pid && s->main_pid_known) {
|
||||
pidref_done(pidref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->main_pid.pid != pidref->pid) {
|
||||
service_unwatch_main_pid(s);
|
||||
exec_status_start(&s->main_exec_status, pidref->pid);
|
||||
}
|
||||
|
||||
s->main_pid = TAKE_PIDREF(*pidref);
|
||||
s->main_pid_known = true;
|
||||
s->main_pid_alien = pid_is_my_child(s->main_pid.pid) == 0;
|
||||
|
||||
if (s->main_pid_alien)
|
||||
log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", s->main_pid.pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int service_set_main_pid(Service *s, pid_t pid) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (pid <= 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (pid == getpid_cached())
|
||||
return -EINVAL;
|
||||
|
||||
if (s->main_pid.pid == pid && s->main_pid_known)
|
||||
return 0;
|
||||
|
||||
r = pidref_set_pid(&pidref, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (s->main_pid.pid != pid) {
|
||||
service_unwatch_main_pid(s);
|
||||
exec_status_start(&s->main_exec_status, pid);
|
||||
}
|
||||
|
||||
s->main_pid = TAKE_PIDREF(pidref);
|
||||
s->main_pid_known = true;
|
||||
s->main_pid_alien = pid_is_my_child(pid) == 0;
|
||||
|
||||
if (s->main_pid_alien)
|
||||
log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", pid);
|
||||
|
||||
return 0;
|
||||
return service_set_main_pidref(s, &pidref);
|
||||
}
|
||||
|
||||
void service_release_socket_fd(Service *s) {
|
||||
|
@ -1108,6 +1121,7 @@ static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) {
|
|||
}
|
||||
|
||||
static int service_load_pid_file(Service *s, bool may_warn) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
bool questionable_pid_file = false;
|
||||
_cleanup_free_ char *k = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
@ -1149,7 +1163,11 @@ static int service_load_pid_file(Service *s, bool may_warn) {
|
|||
if (s->main_pid_known && pid == s->main_pid.pid)
|
||||
return 0;
|
||||
|
||||
r = service_is_suitable_main_pid(s, pid, prio);
|
||||
r = pidref_set_pid(&pidref, pid);
|
||||
if (r < 0)
|
||||
return log_unit_full_errno(UNIT(s), prio, r, "Failed to pin PID " PID_FMT ": %m", pid);
|
||||
|
||||
r = service_is_suitable_main_pid(s, pidref.pid, prio);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
@ -1166,26 +1184,26 @@ static int service_load_pid_file(Service *s, bool may_warn) {
|
|||
|
||||
if (st.st_uid != 0)
|
||||
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EPERM),
|
||||
"New main PID "PID_FMT" does not belong to service, and PID file is not owned by root. Refusing.", pid);
|
||||
"New main PID "PID_FMT" does not belong to service, and PID file is not owned by root. Refusing.", pidref.pid);
|
||||
|
||||
log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, but we'll accept it since PID file is owned by root.", pid);
|
||||
log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, but we'll accept it since PID file is owned by root.", pidref.pid);
|
||||
}
|
||||
|
||||
if (s->main_pid_known) {
|
||||
log_unit_debug(UNIT(s), "Main PID changing: "PID_FMT" -> "PID_FMT, s->main_pid.pid, pid);
|
||||
log_unit_debug(UNIT(s), "Main PID changing: "PID_FMT" -> "PID_FMT, s->main_pid.pid, pidref.pid);
|
||||
|
||||
service_unwatch_main_pid(s);
|
||||
s->main_pid_known = false;
|
||||
} else
|
||||
log_unit_debug(UNIT(s), "Main PID loaded: "PID_FMT, pid);
|
||||
log_unit_debug(UNIT(s), "Main PID loaded: "PID_FMT, pidref.pid);
|
||||
|
||||
r = service_set_main_pid(s, pid);
|
||||
r = service_set_main_pidref(s, &pidref);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_watch_pid(UNIT(s), pid, /* exclusive= */ false);
|
||||
r = unit_watch_pid(UNIT(s), s->main_pid.pid, /* exclusive= */ false);
|
||||
if (r < 0) /* FIXME: we need to do something here */
|
||||
return log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" for service: %m", pid);
|
||||
return log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" for service: %m", s->main_pid.pid);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1212,10 +1230,10 @@ static void service_search_main_pid(Service *s) {
|
|||
if (service_set_main_pid(s, pid) < 0)
|
||||
return;
|
||||
|
||||
r = unit_watch_pid(UNIT(s), pid, /* exclusive= */ false);
|
||||
r = unit_watch_pid(UNIT(s), s->main_pid.pid, /* exclusive= */ false);
|
||||
if (r < 0)
|
||||
/* FIXME: we need to do something here */
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" from: %m", pid);
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" from: %m", s->main_pid.pid);
|
||||
}
|
||||
|
||||
static void service_set_state(Service *s, ServiceState state) {
|
||||
|
@ -2148,8 +2166,8 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
|
|||
UNIT(s),
|
||||
&s->kill_context,
|
||||
kill_operation,
|
||||
s->main_pid.pid,
|
||||
s->control_pid.pid,
|
||||
&s->main_pid,
|
||||
&s->control_pid,
|
||||
s->main_pid_alien);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
@ -2412,7 +2430,7 @@ static void service_enter_start(Service *s) {
|
|||
/* For simple services we immediately start
|
||||
* the START_POST binaries. */
|
||||
|
||||
(void) service_set_main_pid(s, pidref.pid);
|
||||
(void) service_set_main_pidref(s, &pidref);
|
||||
service_enter_start_post(s);
|
||||
|
||||
} else if (s->type == SERVICE_FORKING) {
|
||||
|
@ -2431,7 +2449,7 @@ static void service_enter_start(Service *s) {
|
|||
/* For D-Bus services we know the main pid right away, but wait for the bus name to appear on the
|
||||
* bus. 'notify' and 'exec' services are similar. */
|
||||
|
||||
(void) service_set_main_pid(s, pidref.pid);
|
||||
(void) service_set_main_pidref(s, &pidref);
|
||||
service_set_state(s, SERVICE_START);
|
||||
} else
|
||||
assert_not_reached();
|
||||
|
@ -2700,8 +2718,7 @@ static void service_run_next_main(Service *s) {
|
|||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
(void) service_set_main_pid(s, pidref.pid);
|
||||
|
||||
(void) service_set_main_pidref(s, &pidref);
|
||||
return;
|
||||
|
||||
fail:
|
||||
|
@ -4808,28 +4825,12 @@ static void service_reset_failed(Unit *u) {
|
|||
s->flush_n_restarts = false;
|
||||
}
|
||||
|
||||
static int service_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
|
||||
Service *s = SERVICE(u);
|
||||
|
||||
assert(s);
|
||||
|
||||
return unit_kill_common(u, who, signo, code, value, s->main_pid.pid, s->control_pid.pid, error);
|
||||
static PidRef* service_main_pid(Unit *u) {
|
||||
return &ASSERT_PTR(SERVICE(u))->main_pid;
|
||||
}
|
||||
|
||||
static int service_main_pid(Unit *u) {
|
||||
Service *s = SERVICE(u);
|
||||
|
||||
assert(s);
|
||||
|
||||
return s->main_pid.pid;
|
||||
}
|
||||
|
||||
static int service_control_pid(Unit *u) {
|
||||
Service *s = SERVICE(u);
|
||||
|
||||
assert(s);
|
||||
|
||||
return s->control_pid.pid;
|
||||
static PidRef* service_control_pid(Unit *u) {
|
||||
return &ASSERT_PTR(SERVICE(u))->control_pid;
|
||||
}
|
||||
|
||||
static bool service_needs_console(Unit *u) {
|
||||
|
@ -4889,7 +4890,6 @@ static int service_clean(Unit *u, ExecCleanMask mask) {
|
|||
_cleanup_strv_free_ char **l = NULL;
|
||||
bool may_clean_fdstore = false;
|
||||
Service *s = SERVICE(u);
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
@ -4930,11 +4930,7 @@ static int service_clean(Unit *u, ExecCleanMask mask) {
|
|||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = unit_fork_and_watch_rm_rf(u, l, &pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = pidref_set_pid(&s->control_pid, pid);
|
||||
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -5146,7 +5142,6 @@ const UnitVTable service_vtable = {
|
|||
|
||||
.can_reload = service_can_reload,
|
||||
|
||||
.kill = service_kill,
|
||||
.clean = service_clean,
|
||||
.can_clean = service_can_clean,
|
||||
|
||||
|
|
|
@ -247,10 +247,6 @@ static int slice_stop(Unit *u) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int slice_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
|
||||
return unit_kill_common(u, who, signo, code, value, -1, -1, error);
|
||||
}
|
||||
|
||||
static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
Slice *s = SLICE(u);
|
||||
|
||||
|
@ -436,8 +432,6 @@ const UnitVTable slice_vtable = {
|
|||
.start = slice_start,
|
||||
.stop = slice_stop,
|
||||
|
||||
.kill = slice_kill,
|
||||
|
||||
.freeze = slice_freeze,
|
||||
.thaw = slice_thaw,
|
||||
.can_freeze = slice_can_freeze,
|
||||
|
|
|
@ -1503,9 +1503,9 @@ static int socket_address_listen_in_cgroup(
|
|||
const SocketAddress *address,
|
||||
const char *label) {
|
||||
|
||||
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
||||
_cleanup_close_pair_ int pair[2] = PIPE_EBADF;
|
||||
int fd, r;
|
||||
pid_t pid;
|
||||
|
||||
assert(s);
|
||||
assert(address);
|
||||
|
@ -1597,7 +1597,7 @@ static int socket_address_listen_in_cgroup(
|
|||
fd = receive_one_fd(pair[0], 0);
|
||||
|
||||
/* We synchronously wait for the helper, as it shouldn't be slow */
|
||||
r = wait_for_terminate_and_check("(sd-listen)", pid, WAIT_LOG_ABNORMAL);
|
||||
r = wait_for_terminate_and_check("(sd-listen)", pid.pid, WAIT_LOG_ABNORMAL);
|
||||
if (r < 0) {
|
||||
safe_close(fd);
|
||||
return r;
|
||||
|
@ -1968,8 +1968,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) {
|
|||
}
|
||||
|
||||
static int socket_chown(Socket *s, PidRef *ret_pid) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
pid_t pid;
|
||||
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
@ -2030,15 +2029,11 @@ static int socket_chown(Socket *s, PidRef *ret_pid) {
|
|||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
r = pidref_set_pid(&pidref, pid);
|
||||
r = unit_watch_pid(UNIT(s), pid.pid, /* exclusive= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_watch_pid(UNIT(s), pidref.pid, /* exclusive= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_pid = TAKE_PIDREF(pidref);
|
||||
*ret_pid = TAKE_PIDREF(pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2117,9 +2112,9 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
|
|||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state_to_kill_operation(s, state),
|
||||
-1,
|
||||
s->control_pid.pid,
|
||||
false);
|
||||
/* main_pid= */ NULL,
|
||||
&s->control_pid,
|
||||
/* main_pid_alien= */ false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -2982,9 +2977,9 @@ static int socket_accept_do(Socket *s, int fd) {
|
|||
}
|
||||
|
||||
static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) {
|
||||
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
||||
_cleanup_close_pair_ int pair[2] = PIPE_EBADF;
|
||||
int cfd, r;
|
||||
pid_t pid;
|
||||
|
||||
assert(s);
|
||||
assert(p);
|
||||
|
@ -3034,7 +3029,7 @@ static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) {
|
|||
cfd = receive_one_fd(pair[0], 0);
|
||||
|
||||
/* We synchronously wait for the helper, as it shouldn't be slow */
|
||||
r = wait_for_terminate_and_check("(sd-accept)", pid, WAIT_LOG_ABNORMAL);
|
||||
r = wait_for_terminate_and_check("(sd-accept)", pid.pid, WAIT_LOG_ABNORMAL);
|
||||
if (r < 0) {
|
||||
safe_close(cfd);
|
||||
return r;
|
||||
|
@ -3382,10 +3377,6 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
|
|||
socket_set_state(s, SOCKET_RUNNING);
|
||||
}
|
||||
|
||||
static int socket_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
|
||||
return unit_kill_common(u, who, signo, code, value, -1, SOCKET(u)->control_pid.pid, error);
|
||||
}
|
||||
|
||||
static int socket_get_timeout(Unit *u, usec_t *timeout) {
|
||||
Socket *s = SOCKET(u);
|
||||
usec_t t;
|
||||
|
@ -3414,18 +3405,13 @@ char *socket_fdname(Socket *s) {
|
|||
return s->fdname ?: UNIT(s)->id;
|
||||
}
|
||||
|
||||
static int socket_control_pid(Unit *u) {
|
||||
Socket *s = SOCKET(u);
|
||||
|
||||
assert(s);
|
||||
|
||||
return s->control_pid.pid;
|
||||
static PidRef *socket_control_pid(Unit *u) {
|
||||
return &ASSERT_PTR(SOCKET(u))->control_pid;
|
||||
}
|
||||
|
||||
static int socket_clean(Unit *u, ExecCleanMask mask) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
Socket *s = SOCKET(u);
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
@ -3450,11 +3436,7 @@ static int socket_clean(Unit *u, ExecCleanMask mask) {
|
|||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = unit_fork_and_watch_rm_rf(u, l, &pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = pidref_set_pid(&s->control_pid, pid);
|
||||
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -3576,7 +3558,6 @@ const UnitVTable socket_vtable = {
|
|||
.start = socket_start,
|
||||
.stop = socket_stop,
|
||||
|
||||
.kill = socket_kill,
|
||||
.clean = socket_clean,
|
||||
.can_clean = socket_can_clean,
|
||||
|
||||
|
|
|
@ -763,12 +763,13 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
|
|||
if (s->result == SWAP_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
r = unit_kill_context(UNIT(s),
|
||||
&s->kill_context,
|
||||
state_to_kill_operation(s, state),
|
||||
-1,
|
||||
s->control_pid.pid,
|
||||
false);
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state_to_kill_operation(s, state),
|
||||
/* main_pid= */ NULL,
|
||||
&s->control_pid,
|
||||
/* main_pid_alien= */ false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -1475,10 +1476,6 @@ static void swap_reset_failed(Unit *u) {
|
|||
s->clean_result = SWAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int swap_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
|
||||
return unit_kill_common(u, who, signo, code, value, -1, SWAP(u)->control_pid.pid, error);
|
||||
}
|
||||
|
||||
static int swap_get_timeout(Unit *u, usec_t *timeout) {
|
||||
Swap *s = SWAP(u);
|
||||
usec_t t;
|
||||
|
@ -1515,18 +1512,13 @@ static bool swap_supported(void) {
|
|||
return supported;
|
||||
}
|
||||
|
||||
static int swap_control_pid(Unit *u) {
|
||||
Swap *s = SWAP(u);
|
||||
|
||||
assert(s);
|
||||
|
||||
return s->control_pid.pid;
|
||||
static PidRef* swap_control_pid(Unit *u) {
|
||||
return &ASSERT_PTR(SWAP(u))->control_pid;
|
||||
}
|
||||
|
||||
static int swap_clean(Unit *u, ExecCleanMask mask) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
Swap *s = SWAP(u);
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
@ -1551,11 +1543,7 @@ static int swap_clean(Unit *u, ExecCleanMask mask) {
|
|||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = unit_fork_and_watch_rm_rf(u, l, &pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = pidref_set_pid(&s->control_pid, pid);
|
||||
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -1637,7 +1625,6 @@ const UnitVTable swap_vtable = {
|
|||
.start = swap_start,
|
||||
.stop = swap_stop,
|
||||
|
||||
.kill = swap_kill,
|
||||
.clean = swap_clean,
|
||||
.can_clean = swap_can_clean,
|
||||
|
||||
|
|
140
src/core/unit.c
140
src/core/unit.c
|
@ -2943,7 +2943,7 @@ void unit_unwatch_all_pids(Unit *u) {
|
|||
}
|
||||
|
||||
static void unit_tidy_watch_pids(Unit *u) {
|
||||
pid_t except1, except2;
|
||||
PidRef *except1, *except2;
|
||||
void *e;
|
||||
|
||||
assert(u);
|
||||
|
@ -2956,7 +2956,8 @@ static void unit_tidy_watch_pids(Unit *u) {
|
|||
SET_FOREACH(e, u->pids) {
|
||||
pid_t pid = PTR_TO_PID(e);
|
||||
|
||||
if (pid == except1 || pid == except2)
|
||||
if ((pidref_is_set(except1) && pid == except1->pid) ||
|
||||
(pidref_is_set(except2) && pid == except2->pid))
|
||||
continue;
|
||||
|
||||
if (!pid_is_unwaited(pid))
|
||||
|
@ -3958,18 +3959,6 @@ bool unit_will_restart(Unit *u) {
|
|||
return UNIT_VTABLE(u)->will_restart(u);
|
||||
}
|
||||
|
||||
int unit_kill(Unit *u, KillWho w, int signo, int code, int value, sd_bus_error *error) {
|
||||
assert(u);
|
||||
assert(w >= 0 && w < _KILL_WHO_MAX);
|
||||
assert(SIGNAL_VALID(signo));
|
||||
assert(IN_SET(code, SI_USER, SI_QUEUE));
|
||||
|
||||
if (!UNIT_VTABLE(u)->kill)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return UNIT_VTABLE(u)->kill(u, w, signo, code, value, error);
|
||||
}
|
||||
|
||||
void unit_notify_cgroup_oom(Unit *u, bool managed_oom) {
|
||||
assert(u);
|
||||
|
||||
|
@ -4012,35 +4001,34 @@ static int kill_common_log(pid_t pid, int signo, void *userdata) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int kill_or_sigqueue(pid_t pid, int signo, int code, int value) {
|
||||
assert(pid > 0);
|
||||
static int kill_or_sigqueue(PidRef* pidref, int signo, int code, int value) {
|
||||
assert(pidref_is_set(pidref));
|
||||
assert(SIGNAL_VALID(signo));
|
||||
|
||||
switch (code) {
|
||||
|
||||
case SI_USER:
|
||||
log_debug("Killing " PID_FMT " with signal SIG%s.", pid, signal_to_string(signo));
|
||||
return RET_NERRNO(kill(pid, signo));
|
||||
log_debug("Killing " PID_FMT " with signal SIG%s.", pidref->pid, signal_to_string(signo));
|
||||
return pidref_kill(pidref, signo);
|
||||
|
||||
case SI_QUEUE:
|
||||
log_debug("Enqueuing value %i to " PID_FMT " on signal SIG%s.", value, pid, signal_to_string(signo));
|
||||
return RET_NERRNO(sigqueue(pid, signo, (const union sigval) { .sival_int = value }));
|
||||
log_debug("Enqueuing value %i to " PID_FMT " on signal SIG%s.", value, pidref->pid, signal_to_string(signo));
|
||||
return pidref_sigqueue(pidref, signo, value);
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
int unit_kill_common(
|
||||
int unit_kill(
|
||||
Unit *u,
|
||||
KillWho who,
|
||||
int signo,
|
||||
int code,
|
||||
int value,
|
||||
pid_t main_pid,
|
||||
pid_t control_pid,
|
||||
sd_bus_error *error) {
|
||||
|
||||
PidRef *main_pid, *control_pid;
|
||||
bool killed = false;
|
||||
int ret = 0, r;
|
||||
|
||||
|
@ -4054,24 +4042,30 @@ int unit_kill_common(
|
|||
assert(SIGNAL_VALID(signo));
|
||||
assert(IN_SET(code, SI_USER, SI_QUEUE));
|
||||
|
||||
main_pid = unit_main_pid(u);
|
||||
control_pid = unit_control_pid(u);
|
||||
|
||||
if (!UNIT_HAS_CGROUP_CONTEXT(u) && !main_pid && !control_pid)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit type does not support process killing.");
|
||||
|
||||
if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL)) {
|
||||
if (main_pid < 0)
|
||||
if (!main_pid)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
|
||||
if (main_pid == 0)
|
||||
if (!pidref_is_set(main_pid))
|
||||
return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
|
||||
}
|
||||
|
||||
if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL)) {
|
||||
if (control_pid < 0)
|
||||
if (!control_pid)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
|
||||
if (control_pid == 0)
|
||||
if (!pidref_is_set(control_pid))
|
||||
return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
|
||||
}
|
||||
|
||||
if (control_pid > 0 &&
|
||||
if (pidref_is_set(control_pid) &&
|
||||
IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL)) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
(void) get_process_comm(control_pid, &comm);
|
||||
(void) get_process_comm(control_pid->pid, &comm);
|
||||
|
||||
r = kill_or_sigqueue(control_pid, signo, code, value);
|
||||
if (r < 0) {
|
||||
|
@ -4081,23 +4075,23 @@ int unit_kill_common(
|
|||
sd_bus_error_set_errnof(
|
||||
error, r,
|
||||
"Failed to send signal SIG%s to control process " PID_FMT " (%s): %m",
|
||||
signal_to_string(signo), control_pid, strna(comm));
|
||||
signal_to_string(signo), control_pid->pid, strna(comm));
|
||||
log_unit_warning_errno(
|
||||
u, r,
|
||||
"Failed to send signal SIG%s to control process " PID_FMT " (%s) on client request: %m",
|
||||
signal_to_string(signo), control_pid, strna(comm));
|
||||
signal_to_string(signo), control_pid->pid, strna(comm));
|
||||
} else {
|
||||
log_unit_info(u, "Sent signal SIG%s to control process " PID_FMT " (%s) on client request.",
|
||||
signal_to_string(signo), control_pid, strna(comm));
|
||||
signal_to_string(signo), control_pid->pid, strna(comm));
|
||||
killed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (main_pid > 0 &&
|
||||
if (pidref_is_set(main_pid) &&
|
||||
IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL)) {
|
||||
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
(void) get_process_comm(main_pid, &comm);
|
||||
(void) get_process_comm(main_pid->pid, &comm);
|
||||
|
||||
r = kill_or_sigqueue(main_pid, signo, code, value);
|
||||
if (r < 0) {
|
||||
|
@ -4107,17 +4101,17 @@ int unit_kill_common(
|
|||
sd_bus_error_set_errnof(
|
||||
error, r,
|
||||
"Failed to send signal SIG%s to main process " PID_FMT " (%s): %m",
|
||||
signal_to_string(signo), main_pid, strna(comm));
|
||||
signal_to_string(signo), main_pid->pid, strna(comm));
|
||||
}
|
||||
|
||||
log_unit_warning_errno(
|
||||
u, r,
|
||||
"Failed to send signal SIG%s to main process " PID_FMT " (%s) on client request: %m",
|
||||
signal_to_string(signo), main_pid, strna(comm));
|
||||
signal_to_string(signo), main_pid->pid, strna(comm));
|
||||
|
||||
} else {
|
||||
log_unit_info(u, "Sent signal SIG%s to main process " PID_FMT " (%s) on client request.",
|
||||
signal_to_string(signo), main_pid, strna(comm));
|
||||
signal_to_string(signo), main_pid->pid, strna(comm));
|
||||
killed = true;
|
||||
}
|
||||
}
|
||||
|
@ -4129,7 +4123,7 @@ int unit_kill_common(
|
|||
_cleanup_set_free_ Set *pid_set = NULL;
|
||||
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
pid_set = unit_pid_set(main_pid, control_pid);
|
||||
pid_set = unit_pid_set(main_pid ? main_pid->pid : 0, control_pid ? control_pid->pid : 0);
|
||||
if (!pid_set)
|
||||
return log_oom();
|
||||
|
||||
|
@ -4775,8 +4769,8 @@ int unit_kill_context(
|
|||
Unit *u,
|
||||
KillContext *c,
|
||||
KillOperation k,
|
||||
pid_t main_pid,
|
||||
pid_t control_pid,
|
||||
PidRef* main_pid,
|
||||
PidRef* control_pid,
|
||||
bool main_pid_alien) {
|
||||
|
||||
bool wait_for_exit = false, send_sighup;
|
||||
|
@ -4803,40 +4797,40 @@ int unit_kill_context(
|
|||
IN_SET(k, KILL_TERMINATE, KILL_TERMINATE_AND_LOG) &&
|
||||
sig != SIGHUP;
|
||||
|
||||
if (main_pid > 0) {
|
||||
if (pidref_is_set(main_pid)) {
|
||||
if (log_func)
|
||||
log_func(main_pid, sig, u);
|
||||
log_func(main_pid->pid, sig, u);
|
||||
|
||||
r = kill_and_sigcont(main_pid, sig);
|
||||
r = pidref_kill_and_sigcont(main_pid, sig);
|
||||
if (r < 0 && r != -ESRCH) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
(void) get_process_comm(main_pid, &comm);
|
||||
(void) get_process_comm(main_pid->pid, &comm);
|
||||
|
||||
log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid, strna(comm));
|
||||
log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid->pid, strna(comm));
|
||||
} else {
|
||||
if (!main_pid_alien)
|
||||
wait_for_exit = true;
|
||||
|
||||
if (r != -ESRCH && send_sighup)
|
||||
(void) kill(main_pid, SIGHUP);
|
||||
(void) pidref_kill(main_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
if (control_pid > 0) {
|
||||
if (pidref_is_set(control_pid)) {
|
||||
if (log_func)
|
||||
log_func(control_pid, sig, u);
|
||||
log_func(control_pid->pid, sig, u);
|
||||
|
||||
r = kill_and_sigcont(control_pid, sig);
|
||||
r = pidref_kill_and_sigcont(control_pid, sig);
|
||||
if (r < 0 && r != -ESRCH) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
(void) get_process_comm(control_pid, &comm);
|
||||
(void) get_process_comm(control_pid->pid, &comm);
|
||||
|
||||
log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid, strna(comm));
|
||||
log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid->pid, strna(comm));
|
||||
} else {
|
||||
wait_for_exit = true;
|
||||
|
||||
if (r != -ESRCH && send_sighup)
|
||||
(void) kill(control_pid, SIGHUP);
|
||||
(void) pidref_kill(control_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4845,7 +4839,7 @@ int unit_kill_context(
|
|||
_cleanup_set_free_ Set *pid_set = NULL;
|
||||
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
pid_set = unit_pid_set(main_pid, control_pid);
|
||||
pid_set = unit_pid_set(main_pid ? main_pid->pid : 0, control_pid ? control_pid->pid : 0);
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -4874,7 +4868,7 @@ int unit_kill_context(
|
|||
if (send_sighup) {
|
||||
set_free(pid_set);
|
||||
|
||||
pid_set = unit_pid_set(main_pid, control_pid);
|
||||
pid_set = unit_pid_set(main_pid ? main_pid->pid : 0, control_pid ? control_pid->pid : 0);
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -5120,22 +5114,22 @@ bool unit_is_pristine(Unit *u) {
|
|||
!u->merged_into;
|
||||
}
|
||||
|
||||
pid_t unit_control_pid(Unit *u) {
|
||||
PidRef* unit_control_pid(Unit *u) {
|
||||
assert(u);
|
||||
|
||||
if (UNIT_VTABLE(u)->control_pid)
|
||||
return UNIT_VTABLE(u)->control_pid(u);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pid_t unit_main_pid(Unit *u) {
|
||||
PidRef* unit_main_pid(Unit *u) {
|
||||
assert(u);
|
||||
|
||||
if (UNIT_VTABLE(u)->main_pid)
|
||||
return UNIT_VTABLE(u)->main_pid(u);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void unit_unref_uid_internal(
|
||||
|
@ -5325,7 +5319,8 @@ int unit_set_exec_params(Unit *u, ExecParameters *p) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret) {
|
||||
int unit_fork_helper_process(Unit *u, const char *name, PidRef *ret) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
@ -5336,9 +5331,24 @@ int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret) {
|
|||
|
||||
(void) unit_realize_cgroup(u);
|
||||
|
||||
r = safe_fork(name, FORK_REOPEN_LOG|FORK_DEATHSIG, ret);
|
||||
if (r != 0)
|
||||
r = safe_fork(name, FORK_REOPEN_LOG|FORK_DEATHSIG, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
int q;
|
||||
|
||||
/* Parent */
|
||||
|
||||
q = pidref_set_pid(&pidref, pid);
|
||||
if (q < 0)
|
||||
return q;
|
||||
|
||||
*ret = TAKE_PIDREF(pidref);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Child */
|
||||
|
||||
(void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE);
|
||||
(void) ignore_signals(SIGPIPE);
|
||||
|
@ -5354,8 +5364,8 @@ int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid) {
|
||||
pid_t pid;
|
||||
int unit_fork_and_watch_rm_rf(Unit *u, char **paths, PidRef *ret_pid) {
|
||||
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
@ -5378,11 +5388,11 @@ int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid) {
|
|||
_exit(ret);
|
||||
}
|
||||
|
||||
r = unit_watch_pid(u, pid, true);
|
||||
r = unit_watch_pid(u, pid.pid, /* exclusive= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_pid = pid;
|
||||
*ret_pid = TAKE_PIDREF(pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,14 +9,15 @@
|
|||
#include "sd-id128.h"
|
||||
|
||||
#include "bpf-program.h"
|
||||
#include "cgroup.h"
|
||||
#include "condition.h"
|
||||
#include "emergency-action.h"
|
||||
#include "install.h"
|
||||
#include "list.h"
|
||||
#include "show-status.h"
|
||||
#include "pidref.h"
|
||||
#include "set.h"
|
||||
#include "show-status.h"
|
||||
#include "unit-file.h"
|
||||
#include "cgroup.h"
|
||||
|
||||
typedef struct UnitRef UnitRef;
|
||||
|
||||
|
@ -624,8 +625,6 @@ typedef struct UnitVTable {
|
|||
int (*stop)(Unit *u);
|
||||
int (*reload)(Unit *u);
|
||||
|
||||
int (*kill)(Unit *u, KillWho w, int signo, int code, int value, sd_bus_error *error);
|
||||
|
||||
/* Clear out the various runtime/state/cache/logs/configuration data */
|
||||
int (*clean)(Unit *u, ExecCleanMask m);
|
||||
|
||||
|
@ -719,10 +718,10 @@ typedef struct UnitVTable {
|
|||
usec_t (*get_timeout_start_usec)(Unit *u);
|
||||
|
||||
/* Returns the main PID if there is any defined, or 0. */
|
||||
pid_t (*main_pid)(Unit *u);
|
||||
PidRef* (*main_pid)(Unit *u);
|
||||
|
||||
/* Returns the main PID if there is any defined, or 0. */
|
||||
pid_t (*control_pid)(Unit *u);
|
||||
/* Returns the control PID if there is any defined, or 0. */
|
||||
PidRef* (*control_pid)(Unit *u);
|
||||
|
||||
/* Returns true if the unit currently needs access to the console */
|
||||
bool (*needs_console)(Unit *u);
|
||||
|
@ -913,7 +912,6 @@ int unit_stop(Unit *u);
|
|||
int unit_reload(Unit *u);
|
||||
|
||||
int unit_kill(Unit *u, KillWho w, int signo, int code, int value, sd_bus_error *error);
|
||||
int unit_kill_common(Unit *u, KillWho who, int signo, int code, int value, pid_t main_pid, pid_t control_pid, sd_bus_error *error);
|
||||
|
||||
void unit_notify_cgroup_oom(Unit *u, bool managed_oom);
|
||||
|
||||
|
@ -992,7 +990,7 @@ char* unit_concat_strv(char **l, UnitWriteFlags flags);
|
|||
int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data);
|
||||
int unit_write_settingf(Unit *u, UnitWriteFlags mode, const char *name, const char *format, ...) _printf_(4,5);
|
||||
|
||||
int unit_kill_context(Unit *u, KillContext *c, KillOperation k, pid_t main_pid, pid_t control_pid, bool main_pid_alien);
|
||||
int unit_kill_context(Unit *u, KillContext *c, KillOperation k, PidRef *main_pid, PidRef *control_pid, bool main_pid_alien);
|
||||
|
||||
int unit_make_transient(Unit *u);
|
||||
|
||||
|
@ -1006,8 +1004,8 @@ bool unit_is_unneeded(Unit *u);
|
|||
bool unit_is_upheld_by_active(Unit *u, Unit **ret_culprit);
|
||||
bool unit_is_bound_by_inactive(Unit *u, Unit **ret_culprit);
|
||||
|
||||
pid_t unit_control_pid(Unit *u);
|
||||
pid_t unit_main_pid(Unit *u);
|
||||
PidRef* unit_control_pid(Unit *u);
|
||||
PidRef* unit_main_pid(Unit *u);
|
||||
|
||||
void unit_warn_if_dir_nonempty(Unit *u, const char* where);
|
||||
int unit_fail_if_noncanonical(Unit *u, const char* where);
|
||||
|
@ -1026,8 +1024,8 @@ bool unit_shall_confirm_spawn(Unit *u);
|
|||
|
||||
int unit_set_exec_params(Unit *s, ExecParameters *p);
|
||||
|
||||
int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret);
|
||||
int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid);
|
||||
int unit_fork_helper_process(Unit *u, const char *name, PidRef *ret);
|
||||
int unit_fork_and_watch_rm_rf(Unit *u, char **paths, PidRef *ret);
|
||||
|
||||
void unit_remove_dependencies(Unit *u, UnitDependencyMask mask);
|
||||
|
||||
|
|
Loading…
Reference in a new issue