When a kworker should die, the kworkre is notified through WORKER_DIE flag instead of kthread_should_stop(). This, IIRC, is primarily to keep the test synchronized inside worker_pool lock. WORKER_DIE is first set while holding pool->lock, the lock is dropped and kthread_stop() is called. Unfortunately, this means that there's a slight chance that the target kworker may see WORKER_DIE before kthread_stop() finishes and exits and frees the target task before or during kthread_stop(). Fix it by pinning the target task before setting WORKER_DIE and putting it after kthread_stop() is done. tj: Improved patch description and comment. Moved pinning above WORKER_DIE for better signify what it's protecting.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -1851,6 +1851,12 @@ static void destroy_worker(struct worker *worker) · 1850 unmodified lines | ||
| 1851 | 1851 | if (worker->flags & WORKER_IDLE) |
| 1852 | 1852 | pool->nr_idle--; |
| 1853 | 1853 | |
| 1854 | + /* | |
| 1855 | + * Once WORKER_DIE is set, the kworker may destroy itself at any | |
| 1856 | + * point. Pin to ensure the task stays until we're done with it. | |
| 1857 | + */ | |
| 1858 | + get_task_struct(worker->task); | |
| 1859 | + | |
| 1854 | 1860 | list_del_init(&worker->entry); |
| 1855 | 1861 | worker->flags |= WORKER_DIE; |
| 1856 | 1862 | |
| @@ -1859,6 +1865,7 @@ static void destroy_worker(struct worker *worker) · 2 unmodified lines | ||
| 1859 | 1865 | spin_unlock_irq(&pool->lock); |
| 1860 | 1866 | |
| 1861 | 1867 | kthread_stop(worker->task); |
| 1868 | + put_task_struct(worker->task); | |
| 1862 | 1869 | kfree(worker); |
| 1863 | 1870 | |
| 1864 | 1871 | spin_lock_irq(&pool->lock); |