Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

golang tcp socket can't close after get File()

Tags:

tcp

go

sockets

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?

like image 422
vzex Avatar asked Jan 29 '26 03:01

vzex


1 Answers

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()
like image 165
JimB Avatar answered Jan 30 '26 19:01

JimB



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!