.. | .. |
---|
251 | 251 | set_current_state(TASK_INTERRUPTIBLE); |
---|
252 | 252 | if (pid_ns->pid_allocated == init_pids) |
---|
253 | 253 | break; |
---|
| 254 | + /* |
---|
| 255 | + * Release tasks_rcu_exit_srcu to avoid following deadlock: |
---|
| 256 | + * |
---|
| 257 | + * 1) TASK A unshare(CLONE_NEWPID) |
---|
| 258 | + * 2) TASK A fork() twice -> TASK B (child reaper for new ns) |
---|
| 259 | + * and TASK C |
---|
| 260 | + * 3) TASK B exits, kills TASK C, waits for TASK A to reap it |
---|
| 261 | + * 4) TASK A calls synchronize_rcu_tasks() |
---|
| 262 | + * -> synchronize_srcu(tasks_rcu_exit_srcu) |
---|
| 263 | + * 5) *DEADLOCK* |
---|
| 264 | + * |
---|
| 265 | + * It is considered safe to release tasks_rcu_exit_srcu here |
---|
| 266 | + * because we assume the current task can not be concurrently |
---|
| 267 | + * reaped at this point. |
---|
| 268 | + */ |
---|
| 269 | + exit_tasks_rcu_stop(); |
---|
254 | 270 | schedule(); |
---|
| 271 | + exit_tasks_rcu_start(); |
---|
255 | 272 | } |
---|
256 | 273 | __set_current_state(TASK_RUNNING); |
---|
257 | 274 | |
---|