Index: sys/kern/subr_taskqueue.c =================================================================== --- sys/kern/subr_taskqueue.c +++ sys/kern/subr_taskqueue.c @@ -558,9 +558,33 @@ taskqueue_drain_timeout(struct taskqueue *queue, struct timeout_task *timeout_task) { + u_int pending; - callout_drain(&timeout_task->c); - taskqueue_drain(queue, &timeout_task->t); + if (!queue->tq_spin) + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, __func__); + + do { + pending = 0; + + callout_drain(&timeout_task->c); + + TQ_LOCK(queue); + while (timeout_task->t.ta_pending != 0 || + task_is_running(queue, &timeout_task->t)) { + TQ_SLEEP(queue, &timeout_task->t, &queue->tq_mutex, + PWAIT, "-", 0); + pending = 1; + } + TQ_UNLOCK(queue); + + /* + * In case the taskqueue was pending we need to loop + * in order to fully drain, because the task we are + * draining might invoke the task again and restart + * the callout. + */ + + } while (pending != 0); } static void