Hi Alex

Thanks for your suggestion, I have implemented it, but something is still 
not quite right, the first iteration of the loop to write to the conn still 
encounters a temporary error, even though the internal error is a 
syscall.ECONNRESET.

Please see the updated code below

func TestRemotelyClosedConnectionDetectedOnWrite(t *testing.T) {
listener, err := net.Listen("tcp", ":0")
if err != nil {
t.Fatal(err)
}

wait := make(chan struct{})
go func() {
conn, err := listener.Accept()
if err != nil {
panic(err)
}
err = conn.(*net.TCPConn).SetLinger(0)
if err != nil {
panic(err)
}
err = conn.Close()
if err != nil {
panic(err)
}

wait <- struct{}{}
}()
conn, err := net.Dial("tcp", listener.Addr().String())
if err != nil {
t.Fatal(err)
}
err = conn.(*net.TCPConn).SetLinger(0)
if err != nil {
t.Fatal(err)
}

<-wait
// Allow ample time for any network communication to complete
time.Sleep(time.Second)
for i := 0; i < 10; i++ {
println(i)
_, err = conn.Write([]byte("b"))
if neterr, ok := err.(*net.OpError); ok {
if e, ok := neterr.Err.(*os.SyscallError); ok {
if e.Err == syscall.ECONNRESET && neterr.Temporary() {
// ECONNRESET should not be a temporary error
println("ECONNRESET is not permanent?")
t.Fail()
}
}
}
if neterr, ok := err.(*net.OpError); ok && !neterr.Temporary() {
break
}
}
if err == nil {
t.Fatal("expecting error to be returned when writing")
}
if neterr, ok := err.(net.Error); ok && !neterr.Temporary() {
return
}
t.Fatal("expecting error to be a permanent net.OpError", err)
}




On Tuesday, April 10, 2018 at 5:16:09 PM UTC+1, Alex Efros wrote:
>
> Hi! 
>
> On Tue, Apr 10, 2018 at 07:58:29AM -0700, pierspo...@gmail.com 
> <javascript:> wrote: 
> > I'm trying to understand what is going on under the hood here. 
>
> SO_LINGER (see socket(7)) delay happens. Add this after Accept(): 
>
>         conn, err := listener.Accept() 
>         if err == nil { 
>                 err = conn.(*net.TCPConn).SetLinger(0) 
>         } 
>
> > I would expect a net.Conn after being closed from the far side, to issue 
> an 
> > error if the near side then tries to write to it. On my local machine an 
> > error is returned on the second write, on the go playground all writes 
> > succeed. 
>
> Playground doesn't support TCP, and there is write buffering which 
> postpone returning related error. 
>
> https://play.golang.org/p/JTAetL9no2y 
>
> This example correctly output error in playground: 
>     0 
>     2009/11/10 23:00:00 set tcp 0.0.0.0:2->127.0.0.1:3: Protocol not 
> available 
> and correctly works outside of playground: 
>     0 
>     1 
>     2 
>     3 
>     4 
>     write tcp 127.0.0.1:38900->127.0.0.1:33199: write: connection reset 
> by peer 
> (on very slow system it may output few more numbers because time.Sleep is 
> not really suitable for synchronization). 
>
> -- 
>                         WBR, Alex. 
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to