Home  >  Article  >  Backend Development  >  io.Pipe and deadlock when trying to write/read

io.Pipe and deadlock when trying to write/read

王林
王林forward
2024-02-06 09:40:031118browse

尝试写入/读取时 io.Pipe 和死锁

Question content

I've spent hours trying to understand the underlying logic but making no progress. The code below returns a deadlock after the first iteration. If I close the writer before io.copy the deadlock goes away but nothing is printed (because the writing end of the pipe is closed before reading)

func main() {
    reader, writer := io.pipe()
    c := make(chan string)

    go func() {
        for i := 0; i < 5; i++ {
            text := fmt.sprintf("hello %vth time", i+1)
            c <- text
        }

        close(c)
    }()

    for msg := range c {
        msg = fmt.sprintf("\nreceived from channel -> %v\n", msg)

        go fmt.fprint(writer, msg)
        io.copy(os.stdout, reader)
        writer.close()
    }

}

This is the error after running the code

received from channel -> hello 1th time fatal error: all goroutines
are asleep - deadlock!
goroutine 1 [select]: io.(*pipe).read(0xc000130120, {0xc00013e000,
0x8000, 0xc00011e001?})
/usr/lib/go/src/io/pipe.go:57 +0xb1 io.(*PipeReader).Read(0x0?, {0xc00013e000?, 0xc00011e050?, 0x10?})
/usr/lib/go/src/io/pipe.go:136 +0x25 io.copyBuffer({0x4bde98, 0xc00011e050}, {0x4bddb8, 0xc00012e018}, {0x0, 0x0, 0x0})
/usr/lib/go/src/io/io.go:427 +0x1b2 io.Copy(...)
/usr/lib/go/src/io/io.go:386 os.genericReadFrom(0x101c00002c500?, {0x4bddb8, 0xc00012e018})
/usr/lib/go/src/os/file.go:161 +0x67 os.(*File).ReadFrom(0xc00012e008, {0x4bddb8, 0xc00012e018})
/usr/lib/go/src/os/file.go:155 +0x1b0 io.copyBuffer({0x4bde38, 0xc00012e008}, {0x4bddb8, 0xc00012e018}, {0x0, 0x0, 0x0})
/usr/lib/go/src/io/io.go:413 +0x14b io.Copy(...)
/usr/lib/go/src/io/io.go:386 main.pipetest()
/home/stranger/source-code/golang/ipctest/pipes/main.go:39 +0x1ae main.main()
/home/stranger/source-code/golang/ipctest/pipes/main.go:10 +0x17
goroutine 18 [chan send]: main.pipetest.func1()
/home/stranger/source-code/golang/ipctest/pipes/main.go:29 +0x85 created by main.pipetest
/home/stranger/source-code/golang/ipctest/pipes/main.go:26 +0x17a exit status 2

Correct answer


io.copy Keep trying to copy until the reader reaches eof (in this case, when the pipe is closed ). Since you call writer.close() after after io.copy ends, io.copy will never be seen eof, and hangs forever.

Another problem with your code is that you are trying to close the pipe multiple times (each time the loop code repeats). In general, a closeable object should be closed only once and is assumed to be unavailable after closed. If you need to reuse them, you should create a new instance.

This is a working revision of the code:

func main() {
    c := make(chan string)

    go func() {
        for i := 0; i < 5; i++ {
            text := fmt.Sprintf("hello %vth time", i+1)
            c <- text
        }

        close(c)
    }()

    for msg := range c {
        msg = fmt.Sprintf("\nreceived from channel -> %v\n", msg)

        // Create a new pipe for this message.
        reader, writer := io.Pipe()
        go func() {
            fmt.Fprint(writer, msg)
            // Close the pipe after writing the message.
            writer.Close()
        }()

        io.Copy(os.Stdout, reader)
    }
}

The above is the detailed content of io.Pipe and deadlock when trying to write/read. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete