diff options
author | gVisor bot <gvisor-bot@google.com> | 2020-11-03 03:24:20 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-11-03 03:24:20 +0000 |
commit | ae4df8d6c4f447bc68f7c578282ad5dc03d3b6a1 (patch) | |
tree | 4576416688a733121d90ac726c3f1c4cb6971fbc /pkg/tcpip/stack/neighbor_entry.go | |
parent | f75db1230a6cc509259917da3271ea84b4b1a3ec (diff) | |
parent | c22067d3d4452ac6b65bd56daf796ffeca09e65c (diff) |
Merge release-20201027.0-54-gc22067d3d (automated)
Diffstat (limited to 'pkg/tcpip/stack/neighbor_entry.go')
-rw-r--r-- | pkg/tcpip/stack/neighbor_entry.go | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/pkg/tcpip/stack/neighbor_entry.go b/pkg/tcpip/stack/neighbor_entry.go index aec77610d..493e48031 100644 --- a/pkg/tcpip/stack/neighbor_entry.go +++ b/pkg/tcpip/stack/neighbor_entry.go @@ -17,12 +17,19 @@ package stack import ( "fmt" "sync" + "time" "gvisor.dev/gvisor/pkg/sleep" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" ) +const ( + // immediateDuration is a duration of zero for scheduling work that needs to + // be done immediately but asynchronously to avoid deadlock. + immediateDuration time.Duration = 0 +) + // NeighborEntry describes a neighboring device in the local network. type NeighborEntry struct { Addr tcpip.Address @@ -242,7 +249,12 @@ func (e *neighborEntry) setStateLocked(next NeighborState) { e.job.Schedule(config.RetransmitTimer) } - sendUnicastProbe() + // Send a probe in another gorountine to free this thread of execution + // for finishing the state transition. This is necessary to avoid + // deadlock where sending and processing probes are done synchronously, + // such as loopback and integration tests. + e.job = e.nic.stack.newJob(&e.mu, sendUnicastProbe) + e.job.Schedule(immediateDuration) case Failed: e.notifyWakersLocked() @@ -324,7 +336,12 @@ func (e *neighborEntry) handlePacketQueuedLocked(localAddr tcpip.Address) { e.job.Schedule(config.RetransmitTimer) } - sendMulticastProbe() + // Send a probe in another gorountine to free this thread of execution + // for finishing the state transition. This is necessary to avoid + // deadlock where sending and processing probes are done synchronously, + // such as loopback and integration tests. + e.job = e.nic.stack.newJob(&e.mu, sendMulticastProbe) + e.job.Schedule(immediateDuration) case Stale: e.setStateLocked(Delay) |