Now that the worklist is global, having works pending after wq destruction can easily lead to oops and destroy_workqueue() have several BUG_ON()s to catch these cases. Unfortunately, BUG_ON() doesn't tell much about how the work became pending after the final flush_workqueue(). This patch adds WQ_DYING which is set before the final flush begins. If a work is requested to be queued on a dying workqueue, WARN_ON_ONCE() is triggered and the request is ignored. This clearly indicates which caller is trying to queue a work on a dying workqueue and keeps the system working in most cases. Locking rule comment is updated such that the 'I' rule includes modifying the field from destruction path.
Showing the changes to kernel/workqueue.c (1 of 2 files). Show all
Unified · Split
| @@ -87,7 +87,8 @@ enum { · 86 unmodified lines | |||
| 87 | /* | 87 | /* |
| 88 | * Structure fields follow one of the following exclusion rules. | 88 | * Structure fields follow one of the following exclusion rules. |
| 89 | * | 89 | * |
| 90 | * I: Set during initialization and read-only afterwards. | 90 | * I: Modifiable by initialization/destruction paths and read-only for |
| 91 | * everyone else. | ||
| 91 | * | 92 | * |
| 92 | * P: Preemption protected. Disabling preemption is enough and should | 93 | * P: Preemption protected. Disabling preemption is enough and should |
| 93 | * only be modified and accessed from the local cpu. | 94 | * only be modified and accessed from the local cpu. |
| @@ -944,6 +945,9 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, · 850 unmodified lines | |||
| 944 | 945 | ||
| 945 | debug_work_activate(work); | 946 | debug_work_activate(work); |
| 946 | 947 | ||
| 948 | if (WARN_ON_ONCE(wq->flags & WQ_DYING)) | ||
| 949 | return; | ||
| 950 | |||
| 947 | /* determine gcwq to use */ | 951 | /* determine gcwq to use */ |
| 948 | if (!(wq->flags & WQ_UNBOUND)) { | 952 | if (!(wq->flags & WQ_UNBOUND)) { |
| 949 | struct global_cwq *last_gcwq; | 953 | struct global_cwq *last_gcwq; |
| @@ -2828,6 +2832,7 @@ void destroy_workqueue(struct workqueue_struct *wq) · 1878 unmodified lines | |||
| 2828 | { | 2832 | { |
| 2829 | unsigned int cpu; | 2833 | unsigned int cpu; |
| 2830 | 2834 | ||
| 2835 | wq->flags |= WQ_DYING; | ||
| 2831 | flush_workqueue(wq); | 2836 | flush_workqueue(wq); |
| 2832 | 2837 | ||
| 2833 | /* | 2838 | /* |