summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-04-12 20:19:28 +0000
committergVisor bot <gvisor-bot@google.com>2021-04-12 20:19:28 +0000
commite4a216fe77d2e6467f03594426b4b02b1d3e0e72 (patch)
treef7ab17baf052d5e8762882850724df4c463b64e9 /pkg
parent53b39f1437eff584d29df0e080eb7902ec8969ea (diff)
parenta804b42fe503df227600da0a8c62741af854c2e6 (diff)
Merge release-20210408.0-21-ga804b42fe (automated)
Diffstat (limited to 'pkg')
-rw-r--r--pkg/tcpip/transport/tcp/accept.go37
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