From fa8d922787de1875206a641534cd83eea7b76b05 Mon Sep 17 00:00:00 2001 From: chzyer <0@0xdf.com> Date: Thu, 6 Oct 2016 12:30:22 +0800 Subject: [PATCH] fix deadlock in cancelable stdin --- std.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/std.go b/std.go index ef0b6bb..736fe5d 100644 --- a/std.go +++ b/std.go @@ -4,6 +4,7 @@ import ( "io" "os" "sync" + "sync/atomic" ) var ( @@ -69,6 +70,7 @@ type CancelableStdin struct { r io.Reader mutex sync.Mutex stop chan struct{} + closed int32 notify chan struct{} data []byte read int @@ -101,6 +103,9 @@ loop: func (c *CancelableStdin) Read(b []byte) (n int, err error) { c.mutex.Lock() defer c.mutex.Unlock() + if atomic.LoadInt32(&c.closed) == 1 { + return 0, io.EOF + } c.data = b c.notify <- struct{}{} @@ -113,6 +118,8 @@ func (c *CancelableStdin) Read(b []byte) (n int, err error) { } func (c *CancelableStdin) Close() error { - close(c.stop) + if atomic.CompareAndSwapInt32(&c.closed, 0, 1) { + close(c.stop) + } return nil }