@@ -59,8 +59,7 @@ type Client struct {
5959 stopChan chan struct {}
6060 wg sync.WaitGroup
6161 processDone chan struct {} // closed when the underlying process exits
62- processError error // set before processDone is closed
63- processErrorMu sync.RWMutex // protects processError
62+ processErrorPtr * error // points to error set before processDone is closed
6463}
6564
6665// NewClient creates a new JSON-RPC client
@@ -78,22 +77,17 @@ func NewClient(stdin io.WriteCloser, stdout io.ReadCloser) *Client {
7877// and stores the error that should be returned to pending/future requests.
7978func (c * Client ) SetProcessDone (done chan struct {}, errPtr * error ) {
8079 c .processDone = done
81- // Monitor the channel and copy the error when it closes
82- go func () {
83- <- done
84- if errPtr != nil {
85- c .processErrorMu .Lock ()
86- c .processError = * errPtr
87- c .processErrorMu .Unlock ()
88- }
89- }()
80+ c .processErrorPtr = errPtr
9081}
9182
92- // getProcessError returns the process exit error if the process has exited
83+ // getProcessError returns the process exit error if the process has exited.
84+ // Must only be called after <-c.processDone to ensure visibility of the error
85+ // written before close(done) in the monitor goroutine.
9386func (c * Client ) getProcessError () error {
94- c .processErrorMu .RLock ()
95- defer c .processErrorMu .RUnlock ()
96- return c .processError
87+ if c .processErrorPtr != nil {
88+ return * c .processErrorPtr
89+ }
90+ return nil
9791}
9892
9993// Start begins listening for messages in a background goroutine
0 commit comments