summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2018-03-29 15:12:03 +0000
committerkib <kib@FreeBSD.org>2018-03-29 15:12:03 +0000
commit028129453c33423950e8f20fc548e3fdda3a6747 (patch)
treea5cc96c1aa7d56041ec69a3051359c8607354b40
parentbfc9887efa9faa1191fc127c7a136283693c41e3 (diff)
downloadFreeBSD-src-028129453c33423950e8f20fc548e3fdda3a6747.zip
FreeBSD-src-028129453c33423950e8f20fc548e3fdda3a6747.tar.gz
MFC r331375:
Do not send signals to init directly from shutdown_nice(9), do it from the task context.
-rw-r--r--sys/kern/kern_shutdown.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index f30e436..715e9ef 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/sysproto.h>
+#include <sys/taskqueue.h>
#include <sys/vnode.h>
#include <sys/watchdog.h>
@@ -232,6 +233,26 @@ sys_reboot(struct thread *td, struct reboot_args *uap)
return (error);
}
+static void
+shutdown_nice_task_fn(void *arg, int pending __unused)
+{
+ int howto;
+
+ howto = (uintptr_t)arg;
+ /* Send a signal to init(8) and have it shutdown the world. */
+ PROC_LOCK(initproc);
+ if (howto & RB_POWEROFF)
+ kern_psignal(initproc, SIGUSR2);
+ else if (howto & RB_HALT)
+ kern_psignal(initproc, SIGUSR1);
+ else
+ kern_psignal(initproc, SIGINT);
+ PROC_UNLOCK(initproc);
+}
+
+static struct task shutdown_nice_task = TASK_INITIALIZER(0,
+ &shutdown_nice_task_fn, NULL);
+
/*
* Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC
*/
@@ -239,18 +260,14 @@ void
shutdown_nice(int howto)
{
- if (initproc != NULL) {
- /* Send a signal to init(8) and have it shutdown the world. */
- PROC_LOCK(initproc);
- if (howto & RB_POWEROFF)
- kern_psignal(initproc, SIGUSR2);
- else if (howto & RB_HALT)
- kern_psignal(initproc, SIGUSR1);
- else
- kern_psignal(initproc, SIGINT);
- PROC_UNLOCK(initproc);
+ if (initproc != NULL && !SCHEDULER_STOPPED()) {
+ shutdown_nice_task.ta_context = (void *)(uintptr_t)howto;
+ taskqueue_enqueue(taskqueue_fast, &shutdown_nice_task);
} else {
- /* No init(8) running, so simply reboot. */
+ /*
+ * No init(8) running, or scheduler would not allow it
+ * to run, so simply reboot.
+ */
kern_reboot(howto | RB_NOSYNC);
}
}
OpenPOWER on IntegriCloud