aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/rc.conf.in6
-rw-r--r--src/rc/rc.c26
2 files changed, 29 insertions, 3 deletions
diff --git a/etc/rc.conf.in b/etc/rc.conf.in
index 120eed71..fa28d866 100644
--- a/etc/rc.conf.in
+++ b/etc/rc.conf.in
@@ -57,6 +57,12 @@ rc_logger="NO"
# This still allows the service itself to be stopped when called directly.
#rc_nostop="network"
+# rc will attempt to start crashed services by default.
+# However, it will not stop them by default as that could bring down other
+# critical services.
+#rc_crashed_stop=NO
+#rc_crashed_start=YES
+
##############################################################################
# MISC CONFIGURATION VARIABLES
# There variables are shared between many init scripts
diff --git a/src/rc/rc.c b/src/rc/rc.c
index 9a08546a..83a3701b 100644
--- a/src/rc/rc.c
+++ b/src/rc/rc.c
@@ -571,12 +571,15 @@ do_stop_services(const char *newlevel, bool parallel)
RC_STRINGLIST *deporder, *tmplist;
RC_SERVICE state;
RC_STRINGLIST *nostop;
+ bool crashed;
if (!types_n) {
types_n = rc_stringlist_new();
rc_stringlist_add(types_n, "needsme");
}
+ crashed = rc_conf_yesno("rc_crashed_stop");
+
nostop = rc_stringlist_split(rc_conf_value("rc_nostop"), " ");
TAILQ_FOREACH_REVERSE(service, stop_services, rc_stringlist, entries)
{
@@ -590,6 +593,12 @@ do_stop_services(const char *newlevel, bool parallel)
continue;
}
+ /* If the service has crashed, skip futher checks and just stop
+ it */
+ if (crashed &&
+ rc_service_daemons_crashed(service->value))
+ goto stop;
+
/* If we're in the start list then don't bother stopping us */
svc1 = rc_stringlist_find(start_services, service->value);
if (svc1) {
@@ -628,6 +637,7 @@ do_stop_services(const char *newlevel, bool parallel)
continue;
}
+stop:
/* After all that we can finally stop the blighter! */
pid = service_stop(service->value);
if (pid > 0) {
@@ -649,15 +659,25 @@ do_start_services(bool parallel)
pid_t pid;
bool interactive = false;
RC_SERVICE state;
+ bool crashed = false;
if (!rc_yesno(getenv("EINFO_QUIET")))
interactive = exists(INTERACTIVE);
+ errno = 0;
+ crashed = rc_conf_yesno("rc_crashed_start");
+ if (errno == ENOENT)
+ crashed = true;
TAILQ_FOREACH(service, start_services, entries) {
state = rc_service_state(service->value);
- if (!(state & RC_SERVICE_STOPPED) || state & RC_SERVICE_FAILED)
- continue;
-
+ if (!(state & (RC_SERVICE_STOPPED | RC_SERVICE_FAILED))) {
+ if (crashed &&
+ rc_service_daemons_crashed(service->value))
+ rc_service_mark(service->value,
+ RC_SERVICE_STOPPED);
+ else
+ continue;
+ }
if (!interactive)
interactive = want_interactive();