- switch (fdsi.ssi_signo) {
- case SIGTERM:
- event->sigterm = true;
- break;
- case SIGCHLD:
- if (waitpid(pid, &status, WNOHANG) < 0)
- break;
- if (WIFEXITED(status)) {
- log_debug("'%s' [%u] exit with return code %i", cmd, pid, WEXITSTATUS(status));
- if (WEXITSTATUS(status) != 0)
- err = -1;
- } else if (WIFSIGNALED(status)) {
- log_error("'%s' [%u] terminated by signal %i (%s)", cmd, pid, WTERMSIG(status), strsignal(WTERMSIG(status)));
- err = -1;
- } else if (WIFSTOPPED(status)) {
- log_error("'%s' [%u] stopped", cmd, pid);
- err = -1;
- } else if (WIFCONTINUED(status)) {
- log_error("'%s' [%u] continued", cmd, pid);
- err = -1;
- } else {
- log_error("'%s' [%u] exit with status 0x%04x", cmd, pid, status);
- err = -1;
- }
- pid = 0;
- break;
+ return 1;
+}
+
+static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
+ Spawn *spawn = userdata;
+
+ assert(spawn);
+
+ switch (si->si_code) {
+ case CLD_EXITED:
+ if (si->si_status == 0) {
+ log_debug("Process '%s' succeeded.", spawn->cmd);
+ sd_event_exit(sd_event_source_get_event(s), 0);
+
+ return 1;
+ } else if (spawn->accept_failure)
+ log_debug("Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
+ else
+ log_warning("Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
+
+ break;
+ case CLD_KILLED:
+ case CLD_DUMPED:
+ log_warning("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
+
+ break;
+ default:
+ log_error("Process '%s' failed due to unknown reason.", spawn->cmd);
+ }
+
+ sd_event_exit(sd_event_source_get_event(s), -EIO);
+
+ return 1;
+}
+
+static int spawn_wait(struct udev_event *event,
+ usec_t timeout_usec,
+ usec_t timeout_warn_usec,
+ const char *cmd, pid_t pid,
+ bool accept_failure) {
+ Spawn spawn = {
+ .cmd = cmd,
+ .pid = pid,
+ .accept_failure = accept_failure,
+ };
+ _cleanup_event_unref_ sd_event *e = NULL;
+ int r, ret;
+
+ r = sd_event_new(&e);
+ if (r < 0)
+ return r;
+
+ if (timeout_usec > 0) {
+ usec_t usec, age_usec;
+
+ usec = now(clock_boottime_or_monotonic());
+ age_usec = usec - event->birth_usec;
+ if (age_usec < timeout_usec) {
+ if (timeout_warn_usec > 0 && timeout_warn_usec < timeout_usec && age_usec < timeout_warn_usec) {
+ spawn.timeout_warn = timeout_warn_usec - age_usec;
+
+ r = sd_event_add_time(e, NULL, clock_boottime_or_monotonic(),
+ usec + spawn.timeout_warn, USEC_PER_SEC,
+ on_spawn_timeout_warning, &spawn);
+ if (r < 0)
+ return r;