Skip to content

Instantly share code, notes, and snippets.

@wrfly
Last active October 18, 2018 07:18
Show Gist options
  • Save wrfly/31bd1e5ed68125b78ece57b6470d4858 to your computer and use it in GitHub Desktop.
Save wrfly/31bd1e5ed68125b78ece57b6470d4858 to your computer and use it in GitHub Desktop.
io tee problem
package main
import (
"flag"
"fmt"
"io"
"time"
)
func newReader() io.Reader {
pr, pw := io.Pipe()
go func() {
for {
s := fmt.Sprint(time.Now().UnixNano())
pw.Write([]byte(s))
time.Sleep(time.Second)
}
}()
return pr
}
func read(source string, r io.Reader, notRead bool) {
if notRead {
time.Sleep(time.Hour)
}
buff := make([]byte, 1e3)
for {
n, err := r.Read(buff)
if err != nil {
break
}
fmt.Printf("read from [%s]: %s\n", source, buff[:n])
}
}
func main() {
mode := flag.Int("mode", 1, "1=read all; 2=not read teeReader; 3=not read pipeReader")
flag.Parse()
oriReader := newReader()
pipeReader, pw := io.Pipe()
teeReader := io.TeeReader(oriReader, pw)
switch *mode {
case 1:
fmt.Println("read all (mode 1)")
go read("teeReader", teeReader, false)
go read("pipeReader", pipeReader, false)
case 2:
fmt.Println("not read teeReader (mode 2)")
// change the order will solve it but no outputs neither
read("pipeReader", pipeReader, false)
go read("teeReader", teeReader, true)
case 3:
fmt.Println("not read pipeReader (mode 3)")
// change the order will solve it but no outputs neither
read("teeReader", teeReader, false)
go read("pipeReader", pipeReader, true)
}
c := make(chan bool)
<-c
}
@wrfly
Copy link
Author

wrfly commented Oct 18, 2018

➜  io.tee go run main.go -mode 3
not read pipeReader (mode 3)
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select]:
io.(*pipe).Write(0xc420092140, 0xc42009e000, 0x13, 0x3e8, 0x0, 0x0, 0x0)
	/usr/local/go/src/io/pipe.go:87 +0x1e3
io.(*PipeWriter).Write(0xc42000c040, 0xc42009e000, 0x13, 0x3e8, 0x13, 0x0, 0x0)
	/usr/local/go/src/io/pipe.go:153 +0x4c
io.(*teeReader).Read(0xc42000a060, 0xc42009e000, 0x3e8, 0x3e8, 0x3e8, 0x3e8, 0x1d)
	/usr/local/go/src/io/io.go:535 +0xb1
main.read(0x10d3a57, 0x9, 0x10e60e0, 0xc42000a060, 0x0)
	/Users/shaun.fu/test/go/io.tee/main.go:28 +0x183
main.main()
	/Users/shaun.fu/test/go/io.tee/main.go:59 +0x2f0

goroutine 5 [select]:
io.(*pipe).Write(0xc4200920f0, 0xc420018260, 0x13, 0x20, 0x0, 0x0, 0x0)
	/usr/local/go/src/io/pipe.go:87 +0x1e3
io.(*PipeWriter).Write(0xc42000c030, 0xc420018260, 0x13, 0x20, 0x13, 0x20, 0x0)
	/usr/local/go/src/io/pipe.go:153 +0x4c
main.newReader.func1(0xc42000c030)
	/Users/shaun.fu/test/go/io.tee/main.go:15 +0xfb
created by main.newReader
	/Users/shaun.fu/test/go/io.tee/main.go:12 +0x149
exit status 2

@wrfly
Copy link
Author

wrfly commented Oct 18, 2018

➜  io.tee go run main.go -mode 2
not read teeReader (mode 2)
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select]:
io.(*pipe).Read(0xc420092140, 0xc42009c000, 0x3e8, 0x3e8, 0x10afc40, 0x1, 0xc42009c000)
	/usr/local/go/src/io/pipe.go:50 +0x115
io.(*PipeReader).Read(0xc42000c038, 0xc42009c000, 0x3e8, 0x3e8, 0x3e8, 0x3e8, 0x1c)
	/usr/local/go/src/io/pipe.go:127 +0x4c
main.read(0x10d3c0d, 0xa, 0x10e60a0, 0xc42000c038, 0x0)
	/Users/shaun.fu/test/go/io.tee/main.go:28 +0x183
main.main()
	/Users/shaun.fu/test/go/io.tee/main.go:55 +0x3bd

goroutine 5 [select]:
io.(*pipe).Write(0xc4200920f0, 0xc42009e040, 0x13, 0x20, 0x0, 0x0, 0x0)
	/usr/local/go/src/io/pipe.go:87 +0x1e3
io.(*PipeWriter).Write(0xc42000c030, 0xc42009e040, 0x13, 0x20, 0x13, 0x20, 0x0)
	/usr/local/go/src/io/pipe.go:153 +0x4c
main.newReader.func1(0xc42000c030)
	/Users/shaun.fu/test/go/io.tee/main.go:15 +0xfb
created by main.newReader
	/Users/shaun.fu/test/go/io.tee/main.go:12 +0x149
exit status 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment