3

Please see the code below:

    package main
    import "net"
    import "log"
    import "bufio"
    import "time"

    func main() {
             l,_:=net.Listen("tcp", ":8888")
             for {
                     conn, _ := l.Accept()
                     log.Println("get conn", conn.RemoteAddr())
                     go func() {
                             f, _:=conn.(*net.TCPConn).File()
                             d:=f.Fd()
                             log.Println(d)
                             f.Close()
                             arr := make([]byte, 1000)
                             reader := bufio.NewReader(conn)
                             time.AfterFunc(3*time.Second, func() {
                                     log.Println("close conn", conn.RemoteAddr())
                                     conn.Close()
                             })
                             for {
                                     size, err := reader.Read(arr)
                                     if err != nil {
                                             break
                                     }
                                     log.Println("sss", arr[:size])
                             }
                     }()
             }
    }

when the program start,I use telnet to connect the localhost:8888,after 3 seconds,the server will kill me out, but the socket status is still ESTABLISHED when I use netstat to watch.If I remove the File() function, the socket can be closed normally.How can I fix this?

3
  • 3
    Never ignore errors. For example code at minimum do if err != nil {log.Fatal(err)}. You make everyone looking at your code wonder if there is some error from Listen or Accept (or Close) or File() that is just being ignored. Commented Mar 10, 2015 at 17:16
  • Can you use defer f.Close() just on the next line after you open the file? Commented Mar 10, 2015 at 20:01
  • @DaveC ok,you're very cautious Commented Mar 11, 2015 at 3:01

1 Answer 1

11

This is caused by the FDs being put into blocking mode. Once that happens, you're no longer using the runtime network poller, and have to use the socket as if you were using blocking calls and multiple threads. Underneath, a blocking recv call on a socket can't be interrupted by a close in another thread.

A workaround may be to force the FD back into non-blocking mode before closing it:

syscall.SetNonblock(int(d), true)
f.Close()

You can also shutdown the socket for reading before calling close:

conn.CloseRead()
conn.Close()
Sign up to request clarification or add additional context in comments.

1 Comment

if I remove the for { read ...} loop, the close() function is good, so I guess there is some lock bug during close()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.