diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 575d092fa746..13ea688f2761 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1469,12 +1469,19 @@ static void destroy_worker(struct worker *worker) if (worker->flags & WORKER_IDLE) gcwq->nr_idle--; + /* + * Once WORKER_DIE is set, the kworker may destroy itself at any + * point. Pin to ensure the task stays until we're done with it. + */ + get_task_struct(worker->task); + list_del_init(&worker->entry); worker->flags |= WORKER_DIE; spin_unlock_irq(&gcwq->lock); kthread_stop(worker->task); + put_task_struct(worker->task); kfree(worker); spin_lock_irq(&gcwq->lock);