From 46d94f83259b5a3985a1c001a96276c1a901902d Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Tue, 17 Oct 2017 22:08:17 -0600 Subject: [PATCH] socketClient: fix and test for StopForError deadlock Fixes https://github.com/tendermint/abci/issues/114. Fix and test for StopForError deadlock due to accidental Mutex misuse. The test should return instantenously if StopForError works without erraneous contention, lest it regressed. --- client/socket_client.go | 2 +- client/socket_client_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 client/socket_client_test.go diff --git a/client/socket_client.go b/client/socket_client.go index fd9d0ae9a..1045dea78 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -97,11 +97,11 @@ func (cli *socketClient) OnStop() { // Stop the client and set the error func (cli *socketClient) StopForError(err error) { - cli.mtx.Lock() if !cli.IsRunning() { return } + cli.mtx.Lock() if cli.err == nil { cli.err = err } diff --git a/client/socket_client_test.go b/client/socket_client_test.go new file mode 100644 index 000000000..814d5a68c --- /dev/null +++ b/client/socket_client_test.go @@ -0,0 +1,28 @@ +package abcicli_test + +import ( + "errors" + "testing" + "time" + + "github.com/tendermint/abci/client" +) + +func TestSocketClientStopForErrorDeadlock(t *testing.T) { + c := abcicli.NewSocketClient(":80", false) + err := errors.New("foo-tendermint") + + // See Issue https://github.com/tendermint/abci/issues/114 + doneChan := make(chan bool) + go func() { + defer close(doneChan) + c.StopForError(err) + c.StopForError(err) + }() + + select { + case <-doneChan: + case <-time.After(time.Second * 4): + t.Fatalf("Test took too long, potential deadlock still exists") + } +}