• Dmitry Vyukov's avatar
    runtime: fix spurious deadlock in netpoll · 776aecaf
    Dmitry Vyukov authored
    There is a small possibility that runtime deadlocks when netpoll is just activated.
    Consider the following scenario:
    GOMAXPROCS=1
    epfd=-1 (netpoll is not activated yet)
    A thread is in findrunnable, sets sched.lastpoll=0, calls netpoll(true),
    which returns nil. Now the thread is descheduled for some time.
    Then sysmon retakes a P from syscall and calls handoffp.
    The "If this is the last running P and nobody is polling network" check in handoffp fails,
    since the first thread set sched.lastpoll=0. So handoffp decides that there is already
    a thread that polls network and so it calls pidleput.
    Now the first thread is scheduled again, finds no work and calls stopm.
    There is no thread that polls network and so checkdead reports deadlock.
    
    To fix this, don't set sched.lastpoll=0 when netpoll is not activated.
    
    The deadlock can happen if cgo is disabled (-tag=netgo) and only on program startup
    (when netpoll is just activated).
    
    The test is from issue 5216 that lead to addition of the
    "If this is the last running P and nobody is polling network" check in handoffp.
    
    Update issue 9576.
    
    Change-Id: I9405f627a4d37bd6b99d5670d4328744aeebfc7a
    Reviewed-on: https://go-review.googlesource.com/2750Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
    776aecaf
netpoll.go 11.6 KB