• Peter Zijlstra's avatar
    sched/wait: Fix a kthread race with wait_woken() · cb6538e7
    Peter Zijlstra authored
    There is a race between kthread_stop() and the new wait_woken() that
    can result in a lack of progress.
    
    CPU 0                                    | CPU 1
                                             |
    rfcomm_run()                             | kthread_stop()
      ...                                    |
      if (!test_bit(KTHREAD_SHOULD_STOP))    |
                                             |   set_bit(KTHREAD_SHOULD_STOP)
                                             |   wake_up_process()
        wait_woken()                         |   wait_for_completion()
          set_current_state(INTERRUPTIBLE)   |
          if (!WQ_FLAG_WOKEN)                |
            schedule_timeout()               |
                                             |
    
    After which both tasks will wait.. forever.
    
    Fix this by having wait_woken() check for kthread_should_stop() but
    only for kthreads (obviously).
    Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Cc: Peter Hurley <peter@hurleysoftware.com>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    cb6538e7
wait.c 17.7 KB