From ef49aa7e080d85dd3b510de2408b82fc3e8e7668 Mon Sep 17 00:00:00 2001 From: James Shubin Date: Fri, 30 Mar 2018 06:36:04 -0400 Subject: [PATCH] lang: Don't race with a ^C to the obj.lang calls If we trigger a close, we must not run the LangClose before we've exited from the loop, because that loop could race and run code which depends on LangClose not having run first. So run the loop shutdown, then let the wait group expire, before shutting down the lang. --- lang/gapi.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lang/gapi.go b/lang/gapi.go index e450755d..353aaaaa 100644 --- a/lang/gapi.go +++ b/lang/gapi.go @@ -178,7 +178,10 @@ func (obj *GAPI) Next() chan gapi.Next { Err: fmt.Errorf("%s: GAPI is not initialized", Name), Exit: true, // exit, b/c programming error? } - ch <- next + select { + case ch <- next: + case <-obj.closeChan: + } return } startChan := make(chan struct{}) // start signal @@ -259,9 +262,9 @@ func (obj *GAPI) Close() error { if !obj.initialized { return fmt.Errorf("%s: GAPI is not initialized", Name) } - obj.LangClose() // close lang, esp. if blocked in Stream() wait close(obj.closeChan) obj.wg.Wait() + obj.LangClose() // close lang, esp. if blocked in Stream() wait obj.initialized = false // closed = true return nil }