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, [email protected]
> <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 [email protected].
For more options, visit https://groups.google.com/d/optout.