|
|
1abbee |
From 2a0feeb4252cbf1207f45e978fe7eb02bb0182ec Mon Sep 17 00:00:00 2001
|
|
|
fa0155 |
From: Kyle Walker <walker.kyle.t@gmail.com>
|
|
|
fa0155 |
Date: Thu, 30 Jun 2016 15:12:18 -0400
|
|
|
fa0155 |
Subject: [PATCH] manager: Only invoke a single sigchld per unit within a
|
|
|
fa0155 |
cleanup cycle
|
|
|
fa0155 |
|
|
|
fa0155 |
By default, each iteration of manager_dispatch_sigchld() results in a unit level
|
|
|
fa0155 |
sigchld event being invoked. For scope units, this results in a scope_sigchld_event()
|
|
|
fa0155 |
which can seemingly stall for workloads that have a large number of PIDs within the
|
|
|
fa0155 |
scope. The stall exhibits itself as a SIG_0 being initiated for each u->pids entry
|
|
|
fa0155 |
as a result of pid_is_unwaited().
|
|
|
fa0155 |
|
|
|
fa0155 |
v2:
|
|
|
fa0155 |
This patch resolves this condition by only paying to cost of a sigchld in the underlying
|
|
|
fa0155 |
scope unit once per sigchld iteration. A new "sigchldgen" member resides within the
|
|
|
fa0155 |
Unit struct. The Manager is incremented via the sd event loop, accessed via
|
|
|
fa0155 |
sd_event_get_iteration, and the Unit member is set to the same value as the manager each
|
|
|
fa0155 |
time that a sigchld event is invoked. If the Manager iteration value and Unit member
|
|
|
fa0155 |
match, the sigchld event is not invoked for that iteration.
|
|
|
fa0155 |
|
|
|
fa0155 |
Cherry-picked from: 36f20ae3b2975e44b6ef17e453ae06a289e9a122
|
|
|
fa0155 |
Resolves: #1342173
|
|
|
fa0155 |
---
|
|
|
fa0155 |
src/core/manager.c | 13 ++++++++++++-
|
|
|
fa0155 |
src/core/unit.c | 1 +
|
|
|
fa0155 |
src/core/unit.h | 3 +++
|
|
|
fa0155 |
3 files changed, 16 insertions(+), 1 deletion(-)
|
|
|
fa0155 |
|
|
|
fa0155 |
diff --git a/src/core/manager.c b/src/core/manager.c
|
|
Pablo Greco |
48fc63 |
index e5226a8a6f..63693b93a6 100644
|
|
|
fa0155 |
--- a/src/core/manager.c
|
|
|
fa0155 |
+++ b/src/core/manager.c
|
|
|
1abbee |
@@ -1747,14 +1747,25 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
|
|
fa0155 |
}
|
|
|
fa0155 |
|
|
|
fa0155 |
static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
|
|
|
fa0155 |
+ uint64_t iteration;
|
|
|
fa0155 |
+
|
|
|
fa0155 |
assert(m);
|
|
|
fa0155 |
assert(u);
|
|
|
fa0155 |
assert(si);
|
|
|
fa0155 |
|
|
|
fa0155 |
+ sd_event_get_iteration(m->event, &iteration);
|
|
|
fa0155 |
+
|
|
|
fa0155 |
log_unit_debug(u->id, "Child "PID_FMT" belongs to %s", si->si_pid, u->id);
|
|
|
fa0155 |
|
|
|
fa0155 |
unit_unwatch_pid(u, si->si_pid);
|
|
|
fa0155 |
- UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
|
|
|
fa0155 |
+
|
|
|
fa0155 |
+ if (UNIT_VTABLE(u)->sigchld_event) {
|
|
|
fa0155 |
+ if (set_size(u->pids) <= 1 || iteration != u->sigchldgen) {
|
|
|
fa0155 |
+ UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
|
|
|
fa0155 |
+ u->sigchldgen = iteration;
|
|
|
fa0155 |
+ } else
|
|
|
fa0155 |
+ log_debug("%s already issued a sigchld this iteration %llu, skipping. Pids still being watched %d", u->id, iteration, set_size(u->pids));
|
|
|
fa0155 |
+ }
|
|
|
fa0155 |
}
|
|
|
fa0155 |
|
|
|
fa0155 |
static int manager_dispatch_sigchld(Manager *m) {
|
|
|
fa0155 |
diff --git a/src/core/unit.c b/src/core/unit.c
|
|
Pablo Greco |
48fc63 |
index d6ead7d672..d62135d878 100644
|
|
|
fa0155 |
--- a/src/core/unit.c
|
|
|
fa0155 |
+++ b/src/core/unit.c
|
|
|
fa0155 |
@@ -94,6 +94,7 @@ Unit *unit_new(Manager *m, size_t size) {
|
|
|
fa0155 |
u->unit_file_state = _UNIT_FILE_STATE_INVALID;
|
|
|
fa0155 |
u->unit_file_preset = -1;
|
|
|
fa0155 |
u->on_failure_job_mode = JOB_REPLACE;
|
|
|
fa0155 |
+ u->sigchldgen = 0;
|
|
|
fa0155 |
|
|
|
fa0155 |
return u;
|
|
|
fa0155 |
}
|
|
|
fa0155 |
diff --git a/src/core/unit.h b/src/core/unit.h
|
|
Pablo Greco |
48fc63 |
index 0eebc0b891..d936457776 100644
|
|
|
fa0155 |
--- a/src/core/unit.h
|
|
|
fa0155 |
+++ b/src/core/unit.h
|
|
|
fa0155 |
@@ -167,6 +167,9 @@ struct Unit {
|
|
|
fa0155 |
* process SIGCHLD for */
|
|
|
fa0155 |
Set *pids;
|
|
|
fa0155 |
|
|
|
fa0155 |
+ /* Used in sigchld event invocation to avoid repeat events being invoked */
|
|
|
fa0155 |
+ uint64_t sigchldgen;
|
|
|
fa0155 |
+
|
|
|
fa0155 |
/* Used during GC sweeps */
|
|
|
fa0155 |
unsigned gc_marker;
|
|
|
fa0155 |
|