I have this Go connection snippet in a script:
d := net.Dialer{Timeout: time.Second * 5}
c, err := d.Dial("unix", CONFIG.ServiceSocket.Path)
if err != nil {
handleFatalError(err, errorString)
}
defer c.Close()
// send message
message := fmt.Sprintf("{\"action\":\"%s\"}", *Arguments.Action)
_, err = c.Write([]byte(message))
if err != nil {
var errorString = fmt.Sprintf("Write error: %s", err)
handleFatalError(err, errorString)
}
// read response
buf := make([]byte, CONFIG.ServiceSocket.Buffer)
n, err := c.Read(buf[:])
if err != nil {
var errorString = fmt.Sprintf("Read error: %s", err)
handleFatalError(err, errorString)
}
But the script gets frozen with the following sequence:
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/dhcomms/dispatcher.sock"}, 35) = 0
epoll_ctl(4, EPOLL_CTL_ADD, 3, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=74057432, u64=139805554509528}}) = 0
getsockname(3, {sa_family=AF_UNIX}, [112->2]) = 0
getpeername(3, {sa_family=AF_UNIX, sun_path="/var/run/dhcomms/dispatcher.sock"}, [112->35]) = 0
write(3, "{\"action\":\"status\"}", 19) = 19
read(3, 0xc000100000, 1048576) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x6aafd8, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x6aaed8, FUTEX_WAKE_PRIVATE, 1) = 1
epoll_pwait(4, [{EPOLLOUT, {u32=74057432, u64=139805554509528}}], 128, 0, NULL, 0) = 1
epoll_pwait(4,
I would like to capture this EAGAIN error and close the program in an orderly manner instead.
How should I achieve that ?
EDIT [19/6/23]: Added write/read code
I explain here what I finally did, but I don't like it very much because it seems to me a kind of artificial way to solve the issue. The program get blocked reading the socket:
So I wrap it inside a go routine with a channel an apply a timeout to the whole thing:
I didn't find the way to apply a timeout to the unix socket when the EAGAIN error happens. I bet this should be the right way. If someone knows how to do that, please...
NOTE: I used go-version 1.20 and I'm newby in Go.