Do not send signals to init directly from shutdown_nice(9), do it from
the task context. shutdown_nice() is used from the fast interrupt handlers, mostly for console drivers, where we cannot lock blockable locks. Schedule the task in the fast queue to send the signal from the proper context. Reviewed by: imp Discussed with: bde Sponsored by: The FreeBSD Foundation MFC after: 1 week
This commit is contained in:
parent
54f30ad961
commit
c398200721
@ -72,6 +72,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>
|
||||
|
||||
@ -276,6 +277,28 @@ 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_POWERCYCLE)
|
||||
kern_psignal(initproc, SIGWINCH);
|
||||
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
|
||||
*/
|
||||
@ -283,20 +306,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_POWERCYCLE)
|
||||
kern_psignal(initproc, SIGWINCH);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user