diff options
author | gVisor bot <gvisor-bot@google.com> | 2021-04-12 20:19:28 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-04-12 20:19:28 +0000 |
commit | e4a216fe77d2e6467f03594426b4b02b1d3e0e72 (patch) | |
tree | f7ab17baf052d5e8762882850724df4c463b64e9 | |
parent | 53b39f1437eff584d29df0e080eb7902ec8969ea (diff) | |
parent | a804b42fe503df227600da0a8c62741af854c2e6 (diff) |
Merge release-20210408.0-21-ga804b42fe (automated)
-rw-r--r-- | pkg/tcpip/transport/tcp/accept.go | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/pkg/tcpip/transport/tcp/accept.go b/pkg/tcpip/transport/tcp/accept.go index e2bd57ebf..7acc7e7b0 100644 --- a/pkg/tcpip/transport/tcp/accept.go +++ b/pkg/tcpip/transport/tcp/accept.go @@ -398,25 +398,32 @@ func (e *endpoint) deliverAccepted(n *endpoint, withSynCookie bool) { e.mu.Unlock() defer e.pendingAccepted.Done() - e.acceptMu.Lock() - for { - if e.accepted == (accepted{}) { - n.notifyProtocolGoroutine(notifyReset) - break - } - if e.accepted.endpoints.Len() == e.accepted.cap { - e.acceptCond.Wait() - continue - } + // Drop the lock before notifying to avoid deadlock in user-specified + // callbacks. + delivered := func() bool { + e.acceptMu.Lock() + defer e.acceptMu.Unlock() + for { + if e.accepted == (accepted{}) { + return false + } + if e.accepted.endpoints.Len() == e.accepted.cap { + e.acceptCond.Wait() + continue + } - e.accepted.endpoints.PushBack(n) - if !withSynCookie { - atomic.AddInt32(&e.synRcvdCount, -1) + e.accepted.endpoints.PushBack(n) + if !withSynCookie { + atomic.AddInt32(&e.synRcvdCount, -1) + } + return true } + }() + if delivered { e.waiterQueue.Notify(waiter.ReadableEvents) - break + } else { + n.notifyProtocolGoroutine(notifyReset) } - e.acceptMu.Unlock() } // propagateInheritableOptionsLocked propagates any options set on the listening |