diff options
author | kib <kib@FreeBSD.org> | 2018-03-29 15:12:03 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2018-03-29 15:12:03 +0000 |
commit | 028129453c33423950e8f20fc548e3fdda3a6747 (patch) | |
tree | a5cc96c1aa7d56041ec69a3051359c8607354b40 | |
parent | bfc9887efa9faa1191fc127c7a136283693c41e3 (diff) | |
download | FreeBSD-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.c | 39 |
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); } } |