diff --git a/ChangeLog.md b/ChangeLog.md index c08446f2..40ec015e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -7,11 +7,19 @@ All relevant changes are documented in this file. [4.9][UNRELEASED] -------------------- +> [!CAUTION] +> This release changes how Finit reacts to the exit status of `pre:` +> scripts. Finit will now no longer start the main process if its +> `pre:` script fails for any reason. So, if you have pre scripts that, +> e.g., create directories, make sure they are idempotent. + ### Changes - Add individual timeout (optional) support for pre/post/ready scripts - Add support for systems with broken RTC, i.e., those that at power-on may reset the RTC to a random date instead of zero, issue #418 - Add support for detecting "in-container" when in `systemd-nspawn` + - Check exit status of `pre:` scripts, on failure drive service/sysv to + `crashed` state. (The exit code of `post:` scripts remain ignored) - Reset color attributes and clear screen when starting up. This is for boot loaders like GRUB, which leave background color artifacts diff --git a/src/service.c b/src/service.c index e7524d97..581a37aa 100644 --- a/src/service.c +++ b/src/service.c @@ -1943,8 +1943,11 @@ void service_monitor(pid_t lost, int status) } switch (svc->state) { - case SVC_CLEANUP_STATE: case SVC_SETUP_STATE: + /* If the setup phase fails, drive svc to crashed. */ + svc->status = status; + /* fallthrough */ + case SVC_CLEANUP_STATE: dbg("collected script %s(%d), normal exit: %d, signaled: %d, exit code: %d", svc->state == SVC_CLEANUP_STATE ? svc->post_script : svc->pre_script, lost, WIFEXITED(status), WIFSIGNALED(status), WEXITSTATUS(status)); @@ -2478,8 +2481,27 @@ restart: break; case SVC_SETUP_STATE: - if (!svc->pid) - svc_set_state(svc, SVC_STARTING_STATE); + if (!svc->pid) { + int rc = WEXITSTATUS(svc->status); + int ok = WIFEXITED(svc->status); + + if (!ok || rc) { + const char *sig; + + if (WIFSIGNALED(svc->status)) + sig = sig_name(WTERMSIG(svc->status)); + else + sig = "none"; + + logit(LOG_WARNING, "Service %s pre:%s failed, rc: %d sig:%s", + svc_ident(svc, NULL, 0), svc->pre_script, rc, sig); + + svc_set_state(svc, SVC_STOPPING_STATE); + svc_crashing(svc); + } else { + svc_set_state(svc, SVC_STARTING_STATE); + } + } break; case SVC_WAITING_STATE: