|
|
661545 |
From 1ac6c613ef11a9ee9c36b25133cc302c4be1a858 Mon Sep 17 00:00:00 2001
|
|
|
661545 |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
661545 |
Date: Wed, 24 Jan 2018 19:59:55 +0100
|
|
|
661545 |
Subject: [PATCH] core: rework how we count the n_on_console counter
|
|
|
661545 |
|
|
|
661545 |
Let's add a per-unit boolean that tells us whether our unit is currently
|
|
|
661545 |
counted or not. This way it's unlikely we get out of sync again and
|
|
|
661545 |
things are generally more robust.
|
|
|
661545 |
|
|
|
661545 |
This also allows us to remove the counting logic specific to service
|
|
|
661545 |
units (which was in fact mostly a copy from the generic implementation),
|
|
|
661545 |
in favour of fully generic code.
|
|
|
661545 |
|
|
|
661545 |
Replaces: #7824
|
|
|
661545 |
(cherry picked from commit adefcf2821a386184991054ed2bb6dacc90d7419)
|
|
|
661545 |
|
|
|
661545 |
Resolves: #1524359
|
|
|
661545 |
---
|
|
|
661545 |
src/core/manager.c | 15 +++++++++++++++
|
|
|
661545 |
src/core/manager.h | 3 +++
|
|
|
661545 |
src/core/service.c | 20 --------------------
|
|
|
661545 |
src/core/unit.c | 39 +++++++++++++++++++++------------------
|
|
|
661545 |
src/core/unit.h | 1 +
|
|
|
661545 |
5 files changed, 40 insertions(+), 38 deletions(-)
|
|
|
661545 |
|
|
|
661545 |
diff --git a/src/core/manager.c b/src/core/manager.c
|
|
|
661545 |
index 88d156e8fb..4c87ad8a2f 100644
|
|
|
661545 |
--- a/src/core/manager.c
|
|
|
661545 |
+++ b/src/core/manager.c
|
|
|
661545 |
@@ -3379,6 +3379,21 @@ ManagerState manager_state(Manager *m) {
|
|
|
661545 |
return MANAGER_RUNNING;
|
|
|
661545 |
}
|
|
|
661545 |
|
|
|
661545 |
+void manager_ref_console(Manager *m) {
|
|
|
661545 |
+ assert(m);
|
|
|
661545 |
+
|
|
|
661545 |
+ m->n_on_console++;
|
|
|
661545 |
+}
|
|
|
661545 |
+
|
|
|
661545 |
+void manager_unref_console(Manager *m) {
|
|
|
661545 |
+
|
|
|
661545 |
+ assert(m->n_on_console > 0);
|
|
|
661545 |
+ m->n_on_console--;
|
|
|
661545 |
+
|
|
|
661545 |
+ if (m->n_on_console == 0)
|
|
|
661545 |
+ m->no_console_output = false; /* unset no_console_output flag, since the console is definitely free now */
|
|
|
661545 |
+}
|
|
|
661545 |
+
|
|
|
661545 |
static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
|
|
|
661545 |
[MANAGER_INITIALIZING] = "initializing",
|
|
|
661545 |
[MANAGER_STARTING] = "starting",
|
|
|
661545 |
diff --git a/src/core/manager.h b/src/core/manager.h
|
|
|
661545 |
index b0e4cad1fc..cfc564dfb6 100644
|
|
|
661545 |
--- a/src/core/manager.h
|
|
|
661545 |
+++ b/src/core/manager.h
|
|
|
661545 |
@@ -379,5 +379,8 @@ const char *manager_get_runtime_prefix(Manager *m);
|
|
|
661545 |
|
|
|
661545 |
ManagerState manager_state(Manager *m);
|
|
|
661545 |
|
|
|
661545 |
+void manager_ref_console(Manager *m);
|
|
|
661545 |
+void manager_unref_console(Manager *m);
|
|
|
661545 |
+
|
|
|
661545 |
const char *manager_state_to_string(ManagerState m) _const_;
|
|
|
661545 |
ManagerState manager_state_from_string(const char *s) _pure_;
|
|
|
661545 |
diff --git a/src/core/service.c b/src/core/service.c
|
|
|
661545 |
index 8a8f4be149..ea71c9e237 100644
|
|
|
661545 |
--- a/src/core/service.c
|
|
|
661545 |
+++ b/src/core/service.c
|
|
|
661545 |
@@ -914,26 +914,6 @@ static void service_set_state(Service *s, ServiceState state) {
|
|
|
661545 |
if (state == SERVICE_EXITED && UNIT(s)->manager->n_reloading <= 0)
|
|
|
661545 |
unit_destroy_cgroup_if_empty(UNIT(s));
|
|
|
661545 |
|
|
|
661545 |
- /* For remain_after_exit services, let's see if we can "release" the
|
|
|
661545 |
- * hold on the console, since unit_notify() only does that in case of
|
|
|
661545 |
- * change of state */
|
|
|
661545 |
- if (state == SERVICE_EXITED &&
|
|
|
661545 |
- s->remain_after_exit &&
|
|
|
661545 |
- UNIT(s)->manager->n_on_console > 0) {
|
|
|
661545 |
-
|
|
|
661545 |
- ExecContext *ec;
|
|
|
661545 |
-
|
|
|
661545 |
- ec = unit_get_exec_context(UNIT(s));
|
|
|
661545 |
- if (ec && exec_context_may_touch_console(ec)) {
|
|
|
661545 |
- Manager *m = UNIT(s)->manager;
|
|
|
661545 |
-
|
|
|
661545 |
- m->n_on_console --;
|
|
|
661545 |
- if (m->n_on_console == 0)
|
|
|
661545 |
- /* unset no_console_output flag, since the console is free */
|
|
|
661545 |
- m->no_console_output = false;
|
|
|
661545 |
- }
|
|
|
661545 |
- }
|
|
|
661545 |
-
|
|
|
661545 |
if (old_state != state)
|
|
|
661545 |
log_unit_debug(UNIT(s)->id, "%s changed %s -> %s", UNIT(s)->id, service_state_to_string(old_state), service_state_to_string(state));
|
|
|
661545 |
|
|
|
661545 |
diff --git a/src/core/unit.c b/src/core/unit.c
|
|
|
661545 |
index 48358bc026..294c9eb70f 100644
|
|
|
661545 |
--- a/src/core/unit.c
|
|
|
661545 |
+++ b/src/core/unit.c
|
|
|
661545 |
@@ -544,6 +544,9 @@ void unit_free(Unit *u) {
|
|
|
661545 |
u->manager->n_in_gc_queue--;
|
|
|
661545 |
}
|
|
|
661545 |
|
|
|
661545 |
+ if (u->on_console)
|
|
|
661545 |
+ manager_unref_console(u->manager);
|
|
|
661545 |
+
|
|
|
661545 |
condition_free_list(u->conditions);
|
|
|
661545 |
condition_free_list(u->asserts);
|
|
|
661545 |
|
|
|
661545 |
@@ -1741,6 +1744,23 @@ void unit_trigger_notify(Unit *u) {
|
|
|
661545 |
UNIT_VTABLE(other)->trigger_notify(other, u);
|
|
|
661545 |
}
|
|
|
661545 |
|
|
|
661545 |
+static void unit_update_on_console(Unit *u) {
|
|
|
661545 |
+ bool b;
|
|
|
661545 |
+
|
|
|
661545 |
+ assert(u);
|
|
|
661545 |
+
|
|
|
661545 |
+ b = unit_needs_console(u);
|
|
|
661545 |
+ if (u->on_console == b)
|
|
|
661545 |
+ return;
|
|
|
661545 |
+
|
|
|
661545 |
+ u->on_console = b;
|
|
|
661545 |
+ if (b)
|
|
|
661545 |
+ manager_ref_console(u->manager);
|
|
|
661545 |
+ else
|
|
|
661545 |
+ manager_unref_console(u->manager);
|
|
|
661545 |
+
|
|
|
661545 |
+}
|
|
|
661545 |
+
|
|
|
661545 |
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
|
|
|
661545 |
Manager *m;
|
|
|
661545 |
bool unexpected;
|
|
|
661545 |
@@ -1784,24 +1804,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
|
|
|
661545 |
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
|
|
|
661545 |
unit_destroy_cgroup_if_empty(u);
|
|
|
661545 |
|
|
|
661545 |
- /* Note that this doesn't apply to RemainAfterExit services exiting
|
|
|
661545 |
- * successfully, since there's no change of state in that case. Which is
|
|
|
661545 |
- * why it is handled in service_set_state() */
|
|
|
661545 |
- if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) {
|
|
|
661545 |
- ExecContext *ec;
|
|
|
661545 |
-
|
|
|
661545 |
- ec = unit_get_exec_context(u);
|
|
|
661545 |
- if (ec && exec_context_may_touch_console(ec)) {
|
|
|
661545 |
- if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
|
|
|
661545 |
- m->n_on_console --;
|
|
|
661545 |
-
|
|
|
661545 |
- if (m->n_on_console == 0)
|
|
|
661545 |
- /* unset no_console_output flag, since the console is free */
|
|
|
661545 |
- m->no_console_output = false;
|
|
|
661545 |
- } else
|
|
|
661545 |
- m->n_on_console ++;
|
|
|
661545 |
- }
|
|
|
661545 |
- }
|
|
|
661545 |
+ unit_update_on_console(u);
|
|
|
661545 |
|
|
|
661545 |
if (u->job) {
|
|
|
661545 |
unexpected = false;
|
|
|
661545 |
diff --git a/src/core/unit.h b/src/core/unit.h
|
|
|
661545 |
index fa7de11645..719fc95260 100644
|
|
|
661545 |
--- a/src/core/unit.h
|
|
|
661545 |
+++ b/src/core/unit.h
|
|
|
661545 |
@@ -238,6 +238,7 @@ struct Unit {
|
|
|
661545 |
bool no_gc:1;
|
|
|
661545 |
|
|
|
661545 |
bool in_audit:1;
|
|
|
661545 |
+ bool on_console:1;
|
|
|
661545 |
|
|
|
661545 |
bool cgroup_realized:1;
|
|
|
661545 |
bool cgroup_members_mask_valid:1;
|