From 284dcfdd144bef2accd6d72a6189041c9c63bb16 Mon Sep 17 00:00:00 2001
From: Silas Davis <silas@erisindustries.com>
Date: Fri, 9 Sep 2016 15:50:28 +0100
Subject: [PATCH] Fix blocking event subscription in transactAndHold

---
 erisdb/pipe/transactor.go | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/erisdb/pipe/transactor.go b/erisdb/pipe/transactor.go
index c406d9c6..23f6a000 100644
--- a/erisdb/pipe/transactor.go
+++ b/erisdb/pipe/transactor.go
@@ -177,12 +177,25 @@ func (this *transactor) TransactAndHold(privKey, address, data []byte, gasLimit,
 	} else {
 		addr = address
 	}
-	wc := make(chan *types.EventDataCall)
+
+	// We want non-blocking on the first event received (but buffer the value),
+	// after which we want to block (and then discard the value - see below)
+	wc := make(chan *types.EventDataCall, 1)
+
 	subId := fmt.Sprintf("%X", rec.TxHash)
 	this.eventEmitter.Subscribe(subId, types.EventStringAccCall(addr), func(evt types.EventData) {
 		event := evt.(types.EventDataCall)
 		if bytes.Equal(event.TxID, rec.TxHash) {
-			wc <- &event
+			//  Beware the contract of go-events subscribe is that we must not be
+			// blocking in an event callback when we try to unsubscribe!
+			// We work around this by using a non-blocking receive.
+			select {
+			// This is a non-blocking send, but since we are using a buffered
+			// channel of size 1 we will always grab our first event even if we
+			// haven't read from the channel at the time we receive the first event.
+			case wc <- &event:
+			default:
+			}
 		}
 	})
 
-- 
GitLab