mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-12 09:17:44 +03:00
core: unify kill code of mount, service, socket, swap units
This commit is contained in:
parent
f2956e80c9
commit
cd2086fe65
@ -877,56 +877,23 @@ static void mount_enter_mounted(Mount *m, MountResult f) {
|
||||
|
||||
static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
|
||||
int r;
|
||||
Set *pid_set = NULL;
|
||||
bool wait_for_exit = false;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (f != MOUNT_SUCCESS)
|
||||
m->result = f;
|
||||
|
||||
if (m->kill_context.kill_mode != KILL_NONE) {
|
||||
int sig = (state == MOUNT_MOUNTING_SIGTERM ||
|
||||
state == MOUNT_UNMOUNTING_SIGTERM ||
|
||||
state == MOUNT_REMOUNTING_SIGTERM) ? m->kill_context.kill_signal : SIGKILL;
|
||||
r = unit_kill_context(
|
||||
UNIT(m),
|
||||
&m->kill_context,
|
||||
state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM,
|
||||
-1,
|
||||
m->control_pid,
|
||||
false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (m->control_pid > 0) {
|
||||
if (kill_and_sigcont(m->control_pid, sig) < 0 && errno != ESRCH)
|
||||
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"Failed to kill control process %li: %m",
|
||||
(long) m->control_pid);
|
||||
else
|
||||
wait_for_exit = true;
|
||||
}
|
||||
|
||||
if (m->kill_context.kill_mode == KILL_CONTROL_GROUP) {
|
||||
|
||||
if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Exclude the control pid from being killed via the cgroup */
|
||||
if (m->control_pid > 0)
|
||||
if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0)
|
||||
goto fail;
|
||||
|
||||
r = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, sig, true, false, pid_set, NULL);
|
||||
if (r < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"Failed to kill control group: %s",
|
||||
strerror(-r));
|
||||
} else if (r > 0)
|
||||
wait_for_exit = true;
|
||||
|
||||
set_free(pid_set);
|
||||
pid_set = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (wait_for_exit) {
|
||||
if (r > 0) {
|
||||
r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
@ -947,14 +914,15 @@ fail:
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
|
||||
else
|
||||
mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
|
||||
|
||||
if (pid_set)
|
||||
set_free(pid_set);
|
||||
}
|
||||
|
||||
void warn_if_dir_nonempty(const char *unit, const char* where) {
|
||||
assert(unit);
|
||||
assert(where);
|
||||
|
||||
if (dir_is_empty(where) > 0)
|
||||
return;
|
||||
|
||||
log_struct_unit(LOG_NOTICE,
|
||||
unit,
|
||||
"MESSAGE=%s: Directory %s to mount over is not empty, mounting anyway.",
|
||||
|
@ -1955,64 +1955,23 @@ fail:
|
||||
|
||||
static void service_enter_signal(Service *s, ServiceState state, ServiceResult f) {
|
||||
int r;
|
||||
Set *pid_set = NULL;
|
||||
bool wait_for_exit = false;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (f != SERVICE_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
if (s->kill_context.kill_mode != KILL_NONE) {
|
||||
int sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state != SERVICE_STOP_SIGTERM && state != SERVICE_FINAL_SIGTERM,
|
||||
s->main_pid,
|
||||
s->control_pid,
|
||||
s->main_pid_alien);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (s->main_pid > 0) {
|
||||
if (kill_and_sigcont(s->main_pid, sig) < 0 && errno != ESRCH)
|
||||
log_warning_unit(UNIT(s)->id,
|
||||
"Failed to kill main process %li: %m", (long) s->main_pid);
|
||||
else
|
||||
wait_for_exit = !s->main_pid_alien;
|
||||
}
|
||||
|
||||
if (s->control_pid > 0) {
|
||||
if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
log_warning_unit(UNIT(s)->id,
|
||||
"Failed to kill control process %li: %m", (long) s->control_pid);
|
||||
else
|
||||
wait_for_exit = true;
|
||||
}
|
||||
|
||||
if (s->kill_context.kill_mode == KILL_CONTROL_GROUP) {
|
||||
|
||||
pid_set = set_new(trivial_hash_func, trivial_compare_func);
|
||||
if (!pid_set) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
if (s->main_pid > 0)
|
||||
if ((r = set_put(pid_set, LONG_TO_PTR(s->main_pid))) < 0)
|
||||
goto fail;
|
||||
|
||||
if (s->control_pid > 0)
|
||||
if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
|
||||
goto fail;
|
||||
|
||||
r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
|
||||
if (r < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning_unit(UNIT(s)->id,
|
||||
"Failed to kill control group: %s", strerror(-r));
|
||||
} else if (r > 0)
|
||||
wait_for_exit = true;
|
||||
|
||||
set_free(pid_set);
|
||||
pid_set = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (wait_for_exit) {
|
||||
if (r > 0) {
|
||||
if (s->timeout_stop_usec > 0) {
|
||||
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
|
||||
if (r < 0)
|
||||
@ -2035,9 +1994,6 @@ fail:
|
||||
service_enter_stop_post(s, SERVICE_FAILURE_RESOURCES);
|
||||
else
|
||||
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
|
||||
|
||||
if (pid_set)
|
||||
set_free(pid_set);
|
||||
}
|
||||
|
||||
static void service_enter_stop(Service *s, ServiceResult f) {
|
||||
|
@ -1288,54 +1288,23 @@ fail:
|
||||
|
||||
static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
|
||||
int r;
|
||||
Set *pid_set = NULL;
|
||||
bool wait_for_exit = false;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (f != SOCKET_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
if (s->kill_context.kill_mode != KILL_NONE) {
|
||||
int sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_FINAL_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state != SOCKET_STOP_PRE_SIGTERM && state != SOCKET_FINAL_SIGTERM,
|
||||
-1,
|
||||
s->control_pid,
|
||||
false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (s->control_pid > 0) {
|
||||
if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
|
||||
log_warning_unit(UNIT(s)->id,
|
||||
"Failed to kill control process %li: %m",
|
||||
(long) s->control_pid);
|
||||
else
|
||||
wait_for_exit = true;
|
||||
}
|
||||
|
||||
if (s->kill_context.kill_mode == KILL_CONTROL_GROUP) {
|
||||
|
||||
if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Exclude the control pid from being killed via the cgroup */
|
||||
if (s->control_pid > 0)
|
||||
if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
|
||||
goto fail;
|
||||
|
||||
r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
|
||||
if (r < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning_unit(UNIT(s)->id,
|
||||
"Failed to kill control group: %s",
|
||||
strerror(-r));
|
||||
} else if (r > 0)
|
||||
wait_for_exit = true;
|
||||
|
||||
set_free(pid_set);
|
||||
pid_set = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (wait_for_exit) {
|
||||
if (r > 0) {
|
||||
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
@ -1357,9 +1326,6 @@ fail:
|
||||
socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES);
|
||||
else
|
||||
socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
|
||||
|
||||
if (pid_set)
|
||||
set_free(pid_set);
|
||||
}
|
||||
|
||||
static void socket_enter_stop_pre(Socket *s, SocketResult f) {
|
||||
|
@ -646,57 +646,23 @@ static void swap_enter_active(Swap *s, SwapResult f) {
|
||||
|
||||
static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
|
||||
int r;
|
||||
Set *pid_set = NULL;
|
||||
bool wait_for_exit = false;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (f != SWAP_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
if (s->kill_context.kill_mode != KILL_NONE) {
|
||||
int sig = (state == SWAP_ACTIVATING_SIGTERM ||
|
||||
state == SWAP_DEACTIVATING_SIGTERM) ? s->kill_context.kill_signal : SIGKILL;
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state != SWAP_ACTIVATING_SIGTERM && state != SWAP_DEACTIVATING_SIGTERM,
|
||||
-1,
|
||||
s->control_pid,
|
||||
false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (s->control_pid > 0) {
|
||||
if (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH)
|
||||
|
||||
log_warning_unit(UNIT(s)->id,
|
||||
"Failed to kill control process %li: %m",
|
||||
(long) s->control_pid);
|
||||
else
|
||||
wait_for_exit = true;
|
||||
}
|
||||
|
||||
if (s->kill_context.kill_mode == KILL_CONTROL_GROUP) {
|
||||
|
||||
pid_set = set_new(trivial_hash_func, trivial_compare_func);
|
||||
if (!pid_set) {
|
||||
r = log_oom();
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Exclude the control pid from being killed via the cgroup */
|
||||
if (s->control_pid > 0) {
|
||||
r = set_put(pid_set, LONG_TO_PTR(s->control_pid));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
|
||||
if (r < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning_unit(UNIT(s)->id,
|
||||
"Failed to kill control group: %s", strerror(-r));
|
||||
} else if (r > 0)
|
||||
wait_for_exit = true;
|
||||
|
||||
set_free(pid_set);
|
||||
pid_set = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (wait_for_exit) {
|
||||
if (r > 0) {
|
||||
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
@ -712,9 +678,6 @@ fail:
|
||||
"%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
|
||||
|
||||
swap_enter_dead(s, SWAP_FAILURE_RESOURCES);
|
||||
|
||||
if (pid_set)
|
||||
set_free(pid_set);
|
||||
}
|
||||
|
||||
static void swap_enter_activating(Swap *s) {
|
||||
|
@ -2807,6 +2807,82 @@ int unit_remove_drop_in(Unit *u, bool runtime, const char *name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unit_kill_context(
|
||||
Unit *u,
|
||||
KillContext *c,
|
||||
bool sigkill,
|
||||
pid_t main_pid,
|
||||
pid_t control_pid,
|
||||
bool main_pid_alien) {
|
||||
|
||||
int sig, wait_for_exit = 0, r;
|
||||
|
||||
assert(u);
|
||||
assert(c);
|
||||
|
||||
if (c->kill_mode == KILL_NONE)
|
||||
return 0;
|
||||
|
||||
sig = sigkill ? SIGKILL : c->kill_signal;
|
||||
|
||||
if (main_pid > 0) {
|
||||
r = kill_and_sigcont(main_pid, sig);
|
||||
|
||||
if (r < 0 && r != -ESRCH) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
get_process_comm(main_pid, &comm);
|
||||
|
||||
log_warning_unit(u->id, "Failed to kill main process %li (%s): %s",
|
||||
(long) main_pid, strna(comm), strerror(-r));
|
||||
} else
|
||||
wait_for_exit = !main_pid_alien;
|
||||
}
|
||||
|
||||
if (control_pid > 0) {
|
||||
r = kill_and_sigcont(control_pid, sig);
|
||||
|
||||
if (r < 0 && r != -ESRCH) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
get_process_comm(control_pid, &comm);
|
||||
|
||||
log_warning_unit(u->id,
|
||||
"Failed to kill control process %li (%s): %s",
|
||||
(long) control_pid, strna(comm), strerror(-r));
|
||||
} else
|
||||
wait_for_exit = true;
|
||||
}
|
||||
|
||||
if (c->kill_mode == KILL_CONTROL_GROUP) {
|
||||
_cleanup_set_free_ Set *pid_set = NULL;
|
||||
|
||||
pid_set = set_new(trivial_hash_func, trivial_compare_func);
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Exclude the main/control pids from being killed via the cgroup */
|
||||
if (main_pid > 0) {
|
||||
r = set_put(pid_set, LONG_TO_PTR(main_pid));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (control_pid > 0) {
|
||||
r = set_put(pid_set, LONG_TO_PTR(control_pid));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = cgroup_bonding_kill_list(u->cgroup_bondings, sig, true, false, pid_set, NULL);
|
||||
if (r < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_warning_unit(u->id, "Failed to kill control group: %s", strerror(-r));
|
||||
} else if (r > 0)
|
||||
wait_for_exit = true;
|
||||
}
|
||||
|
||||
return wait_for_exit;
|
||||
}
|
||||
|
||||
static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
|
||||
[UNIT_ACTIVE] = "active",
|
||||
[UNIT_RELOADING] = "reloading",
|
||||
|
@ -557,6 +557,8 @@ ExecContext *unit_get_exec_context(Unit *u);
|
||||
int unit_write_drop_in(Unit *u, bool runtime, const char *name, const char *data);
|
||||
int unit_remove_drop_in(Unit *u, bool runtime, const char *name);
|
||||
|
||||
int unit_kill_context(Unit *u, KillContext *c, bool sigkill, pid_t main_pid, pid_t control_pid, bool main_pid_alien);
|
||||
|
||||
const char *unit_active_state_to_string(UnitActiveState i);
|
||||
UnitActiveState unit_active_state_from_string(const char *s);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user