Search code examples
goio

Is it possible to interrupt io.Copy by closing src?


The sample of code:

package main

import (
    "io"
    "os"
    "os/signal"
    "sync"
    "syscall"
)

func main() {
    sigintCh := make(chan os.Signal, 1)
    signal.Notify(sigintCh, syscall.SIGINT, syscall.SIGTERM)

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        io.Copy(os.Stdout, os.Stdin)
    }()

    <-sigintCh

    os.Stdin.Close()

    wg.Wait()
}

If run this sample and try to interrupt by ^C it waits for any input and stops only after sending something to stdin (e.g. just press enter).

I expect that closing Stdin will be like sending EOF, but it doesn't work.


Solution

  • Closing os.Stdin will cause io.Copy to return with error file already closed next time it reads from it (after CTRL-C, try pressing Enter).

    As explained in the File.Close docs:

    Close closes the File, rendering it unusable for I/O.

    You cannot force an EOF return from os.Stdin by closing it (or any other way). Instead, you would need to either wrap os.Stdin and implement your own Read method that conditionally returns EOF, or read a limited number of bytes in a loop.

    You can see some more discussion and possible workarounds on this golang-nuts thread.