+static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
+ Spawn *spawn = userdata;
+ char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX];
+
+ assert(spawn);
+
+ kill_and_sigcont(spawn->pid, SIGKILL);
+
+ log_error("spawned process '%s' ["PID_FMT"] timed out after %s, killing", spawn->cmd, spawn->pid,
+ format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout));
+
+ return 1;
+}
+
+static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
+ Spawn *spawn = userdata;
+ char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX];
+
+ assert(spawn);
+
+ log_warning("spawned process '%s' ["PID_FMT"] is taking longer than %s to complete", spawn->cmd, spawn->pid,
+ format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout));
+
+ 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;
+}
+