Search code examples
goio

Is it possible to find which end causes io.Copy failure?


In my golang program, I use io.Copy() to relay the flow between end1 and end2.

func relay(src, dst net.Conn, stop chan bool) {
    stop <- (io.Copy(src, dst) == nil)
}
func myprog(e1, e2 net.Conn) {
    stop := make(chan bool)
    go relay(e1, e2, stop)
    go relay(e2, e1, stop)
    result := <-stop
    // Which end causes failure? Or both of them?
}

When one of the relay failed, how can I find out which end is closed/dropped. By result? Or call some member function of e1/e2?

Thanks.


Solution

  • First, making two relay sharing a channel and returning an error with no information of which relay it is from, obviously is not helping to understanding which endpoint is faulty.

    Second, you can wrap Read and Write method of each endpoint to notify the error, like:

    type errReader struct {
        r   io.Reader
        err error
    }
    
    func (er *errReader) Read(b []byte) (int, error) {
        n, err := er.r.Read(b)
        er.err = err
        return n, err
    }
    
    type errWriter struct {
        w   io.Writer
        err error
    }
    
    func (ew *errWriter) Write(b []byte) (int, error) {
        n, err := ew.w.Write(b)
        ew.err = err
        return n, err
    }
    

    Note: The above code takes no consideration of concurrent read or write, nor continuation after error (which may set the err value back to nil again) though it should not be a problem for io.Copy. It also does not ignore io.EOF error, so you may want to check it explicitly.