summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-07-01 20:45:49 +0200
committerLennart Poettering <lennart@poettering.net>2009-07-01 20:45:49 +0200
commit713cd59833f7743bc8d6c2ab8e6edf6fc1bc79e4 (patch)
treed9c9217fbb4005c69f9eb1cd4f65dbe7b1e0ddf1
parent12240b580ac6dd4beab1227f087e03caddf47968 (diff)
don't hand out RT while recovering from system lockup
-rw-r--r--rtkit-daemon.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/rtkit-daemon.c b/rtkit-daemon.c
index 7d2b50f..a0b3034 100644
--- a/rtkit-daemon.c
+++ b/rtkit-daemon.c
@@ -154,6 +154,9 @@ static unsigned canary_watchdog_msec = 10000; /* 10s */
/* Watchdog realtime priority */
static unsigned canary_watchdog_realtime_priority = 99;
+/* How long after the canary died shall we refuse further RT requests? */
+static unsigned canary_refusal_sec = 5*60;
+
/* Demote root processes? */
static bool canary_demote_root = FALSE;
@@ -197,6 +200,7 @@ static unsigned n_total_threads = 0;
static const char *proc = NULL;
static int quit_fd = -1, canary_fd = -1;
static pthread_t canary_thread_id = 0, watchdog_thread_id = 0;
+static volatile uint32_t refuse_until = 0;
static const char *get_proc_path(void) {
/* Useful for chroot environments */
@@ -1203,6 +1207,19 @@ finish:
return ret;
}
+static int verify_canary_refusal(void) {
+ struct timespec now;
+
+ assert_se(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
+
+ if (now.tv_sec < refuse_until) {
+ syslog(LOG_WARNING, "Recovering from system lockup, not allowing further RT threads.\n");
+ return -EPERM;
+ }
+
+ return 0;
+}
+
static DBusHandlerResult dbus_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
DBusError error;
DBusMessage *r = NULL;
@@ -1221,6 +1238,11 @@ static DBusHandlerResult dbus_handler(DBusConnection *c, DBusMessage *m, void *u
struct thread *t;
int ret;
+ if ((ret = verify_canary_refusal()) < 0) {
+ assert_se(r = dbus_message_new_error_printf(m, translate_error_forward(ret), strerror(-ret)));
+ goto finish;
+ }
+
if (!dbus_message_get_args(m, &error,
DBUS_TYPE_UINT64, &thread,
DBUS_TYPE_UINT32, &priority,
@@ -1258,6 +1280,11 @@ static DBusHandlerResult dbus_handler(DBusConnection *c, DBusMessage *m, void *u
struct thread *t;
int ret;
+ if ((ret = verify_canary_refusal()) < 0) {
+ assert_se(r = dbus_message_new_error_printf(m, translate_error_forward(ret), strerror(-ret)));
+ goto finish;
+ }
+
if (!dbus_message_get_args(m, &error,
DBUS_TYPE_UINT64, &thread,
DBUS_TYPE_INT32, &priority,
@@ -1501,6 +1528,8 @@ static void* watchdog_thread(void *data) {
if (TIMESPEC_MSEC(last_cheep) + canary_watchdog_msec <= TIMESPEC_MSEC(now)) {
last_cheep = now;
syslog(LOG_WARNING, "The poor little canary died! Taking action.\n");
+ refuse_until = (uint32_t) now.tv_sec + canary_refusal_sec;
+ __sync_synchronize();
reset_all();
continue;
}
@@ -1723,6 +1752,7 @@ enum {
ARG_CANARY_CHEEP_MSEC,
ARG_CANARY_WATCHDOG_MSEC,
ARG_CANARY_DEMOTE_ROOT,
+ ARG_CANARY_REFUSE_SEC,
ARG_STDERR,
ARG_INTROSPECT
};
@@ -1749,6 +1779,7 @@ static const struct option long_options[] = {
{ "canary-cheep-msec", required_argument, 0, ARG_CANARY_CHEEP_MSEC },
{ "canary-watchdog-msec", required_argument, 0, ARG_CANARY_WATCHDOG_MSEC },
{ "canary-demote-root", no_argument, 0, ARG_CANARY_DEMOTE_ROOT },
+ { "canary-refuse-sec", required_argument, 0, ARG_CANARY_REFUSE_SEC },
{ "stderr", no_argument, 0, ARG_STDERR },
{ "introspect", no_argument, 0, ARG_INTROSPECT },
{ NULL, 0, 0, 0}
@@ -1789,7 +1820,9 @@ static void show_help(const char *exe) {
" --canary-cheep-msec=MSEC Canary cheep interval (%u)\n"
" --canary-watchdog-msec=MSEC Watchdog action delay (%u)\n"
" --canary-demote-root When the canary dies demote root\n"
- " processes too?\n\n"
+ " processes too?\n"
+ " --canary-refuse-sec=SEC How long to refuse further requests\n"
+ " after the canary died (%u)\n\n"
" --no-canary Don't run a canary-based RT watchdog\n\n"
" --no-drop-privileges Don't drop privileges\n"
" --no-chroot Don't chroot\n"
@@ -1807,7 +1840,8 @@ static void show_help(const char *exe) {
actions_burst_sec,
actions_per_burst_max,
canary_cheep_msec,
- canary_watchdog_msec);
+ canary_watchdog_msec,
+ canary_refusal_sec);
}
static int parse_command_line(int argc, char *argv[], int *ret) {
@@ -2018,6 +2052,20 @@ static int parse_command_line(int argc, char *argv[], int *ret) {
canary_demote_root = TRUE;
break;
+ case ARG_CANARY_REFUSE_SEC: {
+ char *e = NULL;
+ unsigned long u;
+
+ errno = 0;
+ u = strtoul(optarg, &e, 0);
+ if (errno != 0 || !e || *e) {
+ fprintf(stderr, "--canary-refuse-sec parameter invalid.\n");
+ return -1;
+ }
+ canary_refusal_sec = (uint32_t) u;
+ break;
+ }
+
case ARG_STDERR:
log_stderr = TRUE;
break;