svn commit: r331298 - head/sys/dev/syscons
Konstantin Belousov
kostikbel at gmail.com
Thu Mar 22 11:42:32 UTC 2018
On Thu, Mar 22, 2018 at 05:50:57PM +1100, Bruce Evans wrote:
> On Wed, 21 Mar 2018, Warner Losh wrote:
>
> > On Wed, Mar 21, 2018 at 2:27 PM, Konstantin Belousov <kostikbel at gmail.com>
> > wrote:
> >> ...
> >> Are you saying that fast interrupt handlers call shutdown_nice() ? This
> >> is the quite serious bug on its own. To fix it, shutdown_nice() should
> >> use a fast taskqueue to schedule the task which would lock the process
> >> and send the signal.
> >
> > Is there some way we know we're in a fast interrupt handler? If so, it
> > should be simple to fix. If not, then there's an API change ahead of us...
>
> There is a td_intr_nesting_level flag that might work. (I invented this,
> but don't like its current use.)
But why do we need to know this ? We can always schedule a task in the
fast taskqueue if init is present and can be scheduled.
>
> > But bde is right: the system has to be in good enough shape to cope. I
> > wonder if we should put that coping into kdb_reboot() instead. It's only an
> > issue for <CR> TILDE ^R, which is a fairly edge case.
>
> shutdown_nice() is also called directly from syscons and vt for the reboot,
> halt and poweroff keys. This happens in normal interrupt handler context,
> so there is only a problem when init is not running.
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index e5ea9644ad3..e7c6d4c92b2 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -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);
}
}
More information about the svn-src-all
mailing list