diff options
author | Jamie Liu <jamieliu@google.com> | 2019-09-06 17:23:15 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2019-09-06 17:25:07 -0700 |
commit | 9e1cbdf565a1f5bf5bbc84bad0103fe2289e817c (patch) | |
tree | a314fc1e1eb496f7dfcff6177b85597acf306b91 /pkg/flipcall/flipcall_test.go | |
parent | 98f7fbb59fc5aca00f47a8145ce1227550869cb8 (diff) |
Indicate flipcall synchronization to the Go race detector.
Since each Endpoint has a distinct mapping of the packet window, the Go race
detector does not recognize accesses by connected Endpoints to be related. This
means that this change isn't necessary for the Go race detector to accept
accesses of flipcall.Endpoint.Data(), but it *is* necessary for it to accept
accesses to shared variables outside the scope of flipcall that are
synchronized by flipcall.Endpoint state; see updated test for an example.
RaceReleaseMerge is needed (instead of RaceRelease) because calls to
raceBecomeInactive() from *unrelated* Endpoints can occur in any order.
(DowngradableRWMutex.RUnlock() has a similar property: calls to RUnlock() on
the same DowngradableRWMutex from different goroutines can occur in any order.
Remove the TODO asking to explain this now that this is understood.)
PiperOrigin-RevId: 267705325
Diffstat (limited to 'pkg/flipcall/flipcall_test.go')
-rw-r--r-- | pkg/flipcall/flipcall_test.go | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/pkg/flipcall/flipcall_test.go b/pkg/flipcall/flipcall_test.go index 435e4eeae..168a487ec 100644 --- a/pkg/flipcall/flipcall_test.go +++ b/pkg/flipcall/flipcall_test.go @@ -62,6 +62,9 @@ func (c *testConnection) destroy() { } func testSendRecv(t *testing.T, c *testConnection) { + // This shared variable is used to confirm that synchronization between + // flipcall endpoints is visible to the Go race detector. + state := 0 var serverRun sync.WaitGroup serverRun.Add(1) go func() { @@ -71,11 +74,19 @@ func testSendRecv(t *testing.T, c *testConnection) { t.Errorf("server Endpoint.RecvFirst() failed: %v", err) return } + state++ + if state != 2 { + t.Errorf("shared state counter: got %d, wanted 2", state) + } t.Logf("server Endpoint got packet 1, sending packet 2 and waiting for packet 3") if _, err := c.serverEP.SendRecv(0); err != nil { t.Errorf("server Endpoint.SendRecv() failed: %v", err) return } + state++ + if state != 4 { + t.Errorf("shared state counter: got %d, wanted 4", state) + } t.Logf("server Endpoint got packet 3") }() defer func() { @@ -89,10 +100,18 @@ func testSendRecv(t *testing.T, c *testConnection) { if err := c.clientEP.Connect(); err != nil { t.Fatalf("client Endpoint.Connect() failed: %v", err) } + state++ + if state != 1 { + t.Errorf("shared state counter: got %d, wanted 1", state) + } t.Logf("client Endpoint sending packet 1 and waiting for packet 2") if _, err := c.clientEP.SendRecv(0); err != nil { t.Fatalf("client Endpoint.SendRecv() failed: %v", err) } + state++ + if state != 3 { + t.Errorf("shared state counter: got %d, wanted 3", state) + } t.Logf("client Endpoint got packet 2, sending packet 3") if err := c.clientEP.SendLast(0); err != nil { t.Fatalf("client Endpoint.SendLast() failed: %v", err) |