-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Closed
Labels
Description
I was trying to cleanly close a Unix socket (i.e. stop receiving traffic, read all the socket buffer and then close the socket) but found it a bit cumbersome.
The issue is that the following code blocks indefinitely:
package main
import (
"fmt"
"net"
)
func main() {
var socket = "/tmp/test.sock"
addr, err := net.ResolveUnixAddr("unixgram", socket)
if err != nil {
panic(err)
}
conn, err := net.ListenUnixgram("unixgram", addr)
if err != nil {
panic(err)
}
w, err := net.DialUnix("unixgram", nil, conn.LocalAddr().(*net.UnixAddr))
if err != nil {
panic(err)
}
if _, err := w.Write([]byte("foo")); err != nil {
panic(err)
}
if err := conn.CloseRead(); err != nil {
panic(err)
}
buf := make([]byte, 10)
n, err := conn.Read(buf)
if err != nil {
panic(err)
}
fmt.Println(string(buf[:n])) // Prints foo.
n, err = conn.Read(buf) // Hangs indefinitely. Should it return io.EOF?
if err != nil {
panic(err)
}
fmt.Println(string(buf[:n]))
}
To read all the socket buffer without blocking indefinitely you have to either:
- use
conn.Close()
after a timeout to unblockconn.Read()
- use
conn.File()
andsyscall.SetNonblock()
to read the connection buffer in a non-blocking way
I don't like 1.
since it would make my tests slow or flaky. 2.
works well but it makes the code more complex.
Since after a CloseRead()
, a socket cannot receive more data I think it would make sense that Read
returns an io.EOF
when it reaches the end of the connection buffer.