From 6c6e66f7b2e776add2bfbfbafa9c991c90bc15f4 Mon Sep 17 00:00:00 2001
From: Silas Davis <silas@erisindustries.com>
Date: Fri, 9 Sep 2016 20:17:06 +0100
Subject: [PATCH] Fix blocking event subscription in transactAndHold

---
 manager/eris-mint/transactor.go | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/manager/eris-mint/transactor.go b/manager/eris-mint/transactor.go
index fd920145..23012e4a 100644
--- a/manager/eris-mint/transactor.go
+++ b/manager/eris-mint/transactor.go
@@ -205,13 +205,24 @@ func (this *transactor) TransactAndHold(privKey, address, data []byte, gasLimit,
 	} else {
 		addr = address
 	}
-	wc := make(chan *txs.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 *txs.EventDataCall, 1)
 	subId := fmt.Sprintf("%X", rec.TxHash)
 	this.eventEmitter.Subscribe(subId, txs.EventStringAccCall(addr),
 		func(evt txs.EventData) {
-			event := evt.(txs.EventDataCall)
-			if bytes.Equal(event.TxID, rec.TxHash) {
-				wc <- &event
+			eventDataCall := evt.(txs.EventDataCall)
+			if bytes.Equal(eventDataCall.TxID, rec.TxHash) {
+				// 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 send.
+				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 <- &eventDataCall:
+				default:
+				}
 			}
 		})
 
-- 
GitLab