mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
core/service: destroy runtime data when Type=oneshot services exit
Currently, we have a bunch of Type=oneshot + RemainAfterExit=yes services that make use of credentials. When those exits, the cred mounts remain established, which is pointless and quite annoying. Let's instead destroy the runtime data on SERVICE_EXITED, if no process will be spawned for the unit again.
This commit is contained in:
parent
8b17371b61
commit
c26948c6da
@ -1228,13 +1228,12 @@ static void service_search_main_pid(Service *s) {
|
||||
}
|
||||
|
||||
static void service_set_state(Service *s, ServiceState state) {
|
||||
Unit *u = UNIT(ASSERT_PTR(s));
|
||||
ServiceState old_state;
|
||||
const UnitActiveState *table;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (s->state != state)
|
||||
bus_unit_send_pending_change_signal(UNIT(s), false);
|
||||
bus_unit_send_pending_change_signal(u, false);
|
||||
|
||||
table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
|
||||
|
||||
@ -1268,8 +1267,8 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
SERVICE_DEAD, SERVICE_FAILED,
|
||||
SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_FAILED_BEFORE_AUTO_RESTART, SERVICE_AUTO_RESTART, SERVICE_AUTO_RESTART_QUEUED,
|
||||
SERVICE_DEAD_RESOURCES_PINNED)) {
|
||||
unit_unwatch_all_pids(UNIT(s));
|
||||
unit_dequeue_rewatch_pids(UNIT(s));
|
||||
unit_unwatch_all_pids(u);
|
||||
unit_dequeue_rewatch_pids(u);
|
||||
}
|
||||
|
||||
if (state != SERVICE_START)
|
||||
@ -1278,15 +1277,31 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY))
|
||||
service_stop_watchdog(s);
|
||||
|
||||
/* For the inactive states unit_notify() will trim the cgroup,
|
||||
* but for exit we have to do that ourselves... */
|
||||
if (state == SERVICE_EXITED && !MANAGER_IS_RELOADING(UNIT(s)->manager))
|
||||
unit_prune_cgroup(UNIT(s));
|
||||
if (state == SERVICE_EXITED && !MANAGER_IS_RELOADING(u->manager)) {
|
||||
/* For the inactive states unit_notify() will trim the cgroup. But for exit we have to
|
||||
* do that ourselves... */
|
||||
unit_prune_cgroup(u);
|
||||
|
||||
/* If none of ExecReload= and ExecStop*= is used, we can safely destroy runtime data
|
||||
* as soon as the service enters SERVICE_EXITED. This saves us from keeping the credential mount
|
||||
* for the whole duration of the oneshot service while no processes are actually running,
|
||||
* among other things. */
|
||||
|
||||
bool start_only = true;
|
||||
for (ServiceExecCommand c = SERVICE_EXEC_RELOAD; c < _SERVICE_EXEC_COMMAND_MAX; c++)
|
||||
if (s->exec_command[c]) {
|
||||
start_only = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (start_only)
|
||||
unit_destroy_runtime_data(u, &s->exec_context);
|
||||
}
|
||||
|
||||
if (old_state != state)
|
||||
log_unit_debug(UNIT(s), "Changed %s -> %s", service_state_to_string(old_state), service_state_to_string(state));
|
||||
log_unit_debug(u, "Changed %s -> %s", service_state_to_string(old_state), service_state_to_string(state));
|
||||
|
||||
unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
|
||||
unit_notify(u, table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
|
||||
}
|
||||
|
||||
static usec_t service_coldplug_timeout(Service *s) {
|
||||
|
Loading…
Reference in New Issue
Block a user