| Summary: |
sd_event fails miserably with more than one child process |
| Product: |
systemd
|
Reporter: |
Hristo Venev <hristo> |
| Component: |
general | Assignee: |
Zbigniew Jedrzejewski-Szmek <zbyszek> |
| Status: |
RESOLVED
FIXED
|
QA Contact: |
systemd-bugs |
| Severity: |
normal
|
|
|
| Priority: |
medium
|
|
|
| Version: |
unspecified | |
|
| Hardware: |
Other | |
|
| OS: |
Linux (All) | |
|
| Whiteboard: |
|
|
i915 platform:
|
|
i915 features:
|
|
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.
When a child event is disabled (in order to be freed) and there is no SIGCHLD signal event, sd_event_source_set_enabled will disable SIGCHLD even if there are other child events. My fix also removes some unneeded signalfd updates. diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index b56182d..42b176b 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -1055,11 +1055,9 @@ _public_ int sd_event_add_child( return r; } - e->n_enabled_child_sources ++; - assert_se(sigaddset(&e->sigset, SIGCHLD) == 0); - if (!e->signal_sources || !e->signal_sources[SIGCHLD]) { + if ((!e->signal_sources || !e->signal_sources[SIGCHLD]) && e->n_enabled_child_sources == 0) { r = event_update_signal_fd(e); if (r < 0) { source_free(s); @@ -1067,6 +1065,8 @@ _public_ int sd_event_add_child( } } + e->n_enabled_child_sources ++; + e->need_process_child = true; if (ret) @@ -1451,7 +1451,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { assert(s->event->n_enabled_child_sources > 0); s->event->n_enabled_child_sources--; - if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) { + if ((!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) && s->event->n_enabled_child_sources == 0) { assert_se(sigdelset(&s->event->sigset, SIGCHLD) == 0); event_update_signal_fd(s->event); } @@ -1511,12 +1511,12 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { case SOURCE_CHILD: if (s->enabled == SD_EVENT_OFF) { - s->event->n_enabled_child_sources++; - - if (!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) { + if ((!s->event->signal_sources || !s->event->signal_sources[SIGCHLD]) && s->event->n_enabled_child_sources == 0) { assert_se(sigaddset(&s->event->sigset, SIGCHLD) == 0); event_update_signal_fd(s->event); } + + s->event->n_enabled_child_sources++; } s->enabled = m;