From 35bf3bd6a276fa58fa6ed5a258a7fbc4ba8bce05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= Date: Sat, 16 Jul 2016 21:04:13 +0200 Subject: [PATCH] manager: don't skip sigchld handler for main and control pid for services (#3738) During stop when service has one "regular" pid one main pid and one control pid and the sighld for the regular one is processed first the unit_tidy_watch_pids will skip the main and control pid and does not remove them from u->pids(). But then we skip the sigchld event because we already did one in the iteration and there are two pids in u->pids. v2: Use general unit_main_pid() and unit_control_pid() instead of reaching directly to service structure. Cherry-picked from: ccc2c98e1b0c06861577632440b996ca16cefd53 Resolves: #1342173 --- src/core/busname.c | 10 ++++++++++ src/core/manager.c | 5 ++++- src/core/mount.c | 10 ++++++++++ src/core/service.c | 19 +++++++++++++++++++ src/core/socket.c | 10 ++++++++++ src/core/swap.c | 10 ++++++++++ src/core/unit.c | 18 ++++++++++++++++++ src/core/unit.h | 9 +++++++++ 8 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/core/busname.c b/src/core/busname.c index 43d7607..f626ba9 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -997,6 +997,14 @@ static const char* const busname_state_table[_BUSNAME_STATE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState); +static int busname_control_pid(Unit *u) { + BusName *n = BUSNAME(u); + + assert(n); + + return n->control_pid; +} + static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = { [BUSNAME_SUCCESS] = "success", [BUSNAME_FAILURE_RESOURCES] = "resources", @@ -1047,6 +1055,8 @@ const UnitVTable busname_vtable = { .supported = busname_supported, + .control_pid = busname_control_pid, + .bus_interface = "org.freedesktop.systemd1.BusName", .bus_vtable = bus_busname_vtable, diff --git a/src/core/manager.c b/src/core/manager.c index b63d929..87b5e57 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1756,7 +1756,10 @@ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) { unit_unwatch_pid(u, si->si_pid); if (UNIT_VTABLE(u)->sigchld_event) { - if (set_size(u->pids) <= 1 || iteration != u->sigchldgen) { + if (set_size(u->pids) <= 1 || + iteration != u->sigchldgen || + unit_main_pid(u) == si->si_pid || + unit_control_pid(u) == si->si_pid) { UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status); u->sigchldgen = iteration; } else diff --git a/src/core/mount.c b/src/core/mount.c index 23f63ce..4dc9f2e 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1883,6 +1883,14 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState); +static int mount_control_pid(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + + return m->control_pid; +} + static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = { [MOUNT_EXEC_MOUNT] = "ExecMount", [MOUNT_EXEC_UNMOUNT] = "ExecUnmount", @@ -1944,6 +1952,8 @@ const UnitVTable mount_vtable = { .reset_failed = mount_reset_failed, + .control_pid = mount_control_pid, + .bus_interface = "org.freedesktop.systemd1.Mount", .bus_vtable = bus_mount_vtable, .bus_set_property = bus_mount_set_property, diff --git a/src/core/service.c b/src/core/service.c index ae5e610..f102ef3 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3028,6 +3028,22 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState); +static int service_main_pid(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + return s->main_pid; +} + +static int service_control_pid(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + return s->control_pid; +} + static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { [SERVICE_RESTART_NO] = "no", [SERVICE_RESTART_ON_SUCCESS] = "on-success", @@ -3138,6 +3154,9 @@ const UnitVTable service_vtable = { .notify_cgroup_empty = service_notify_cgroup_empty_event, .notify_message = service_notify_message, + .main_pid = service_main_pid, + .control_pid = service_control_pid, + .bus_name_owner_change = service_bus_name_owner_change, .bus_interface = "org.freedesktop.systemd1.Service", diff --git a/src/core/socket.c b/src/core/socket.c index bc677a2..771af0d 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2648,6 +2648,14 @@ static const char* const socket_state_table[_SOCKET_STATE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState); +static int socket_control_pid(Unit *u) { + Socket *s = SOCKET(u); + + assert(s); + + return s->control_pid; +} + static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { [SOCKET_EXEC_START_PRE] = "StartPre", [SOCKET_EXEC_START_CHOWN] = "StartChown", @@ -2713,6 +2721,8 @@ const UnitVTable socket_vtable = { .reset_failed = socket_reset_failed, + .control_pid = socket_control_pid, + .bus_interface = "org.freedesktop.systemd1.Socket", .bus_vtable = bus_socket_vtable, .bus_set_property = bus_socket_set_property, diff --git a/src/core/swap.c b/src/core/swap.c index 34a2c40..42f9959 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -1426,6 +1426,14 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState); +static int swap_control_pid(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + + return s->control_pid; +} + static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = { [SWAP_EXEC_ACTIVATE] = "ExecActivate", [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate", @@ -1487,6 +1495,8 @@ const UnitVTable swap_vtable = { .reset_failed = swap_reset_failed, + .control_pid = swap_control_pid, + .bus_interface = "org.freedesktop.systemd1.Swap", .bus_vtable = bus_swap_vtable, .bus_set_property = bus_swap_set_property, diff --git a/src/core/unit.c b/src/core/unit.c index 5b2becc..f03f185 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3667,6 +3667,24 @@ int unit_setup_exec_runtime(Unit *u) { return exec_runtime_make(rt, unit_get_exec_context(u), u->id); } +pid_t unit_control_pid(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->control_pid) + return UNIT_VTABLE(u)->control_pid(u); + + return 0; +} + +pid_t unit_main_pid(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->main_pid) + return UNIT_VTABLE(u)->main_pid(u); + + return 0; +} + static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = { [UNIT_ACTIVE] = "active", [UNIT_RELOADING] = "reloading", diff --git a/src/core/unit.h b/src/core/unit.h index d936457..35287a5 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -399,6 +399,12 @@ struct UnitVTable { int (*get_timeout)(Unit *u, uint64_t *timeout); + /* Returns the main PID if there is any defined, or 0. */ + pid_t (*main_pid)(Unit *u); + + /* Returns the main PID if there is any defined, or 0. */ + pid_t (*control_pid)(Unit *u); + /* This is called for each unit type and should be used to * enumerate existing devices and load them. However, * everything that is loaded here should still stay in @@ -610,6 +616,9 @@ int unit_make_transient(Unit *u); int unit_require_mounts_for(Unit *u, const char *path); +pid_t unit_control_pid(Unit *u); +pid_t unit_main_pid(Unit *u); + const char *unit_active_state_to_string(UnitActiveState i) _const_; UnitActiveState unit_active_state_from_string(const char *s) _pure_;