Richard W.M. Jones
2021-Feb-04 18:10 UTC
[Libguestfs] [PATCH libnbd 0/2] Fix for connect(2) returning EAGAIN.
I don't believe there's really a good way to fix this, but we can at least print a better error message. Thanks: Xin Long and Lukas Doktor
Richard W.M. Jones
2021-Feb-04 18:10 UTC
[Libguestfs] [PATCH libnbd 1/2] generator: Refactor CONNECT.START state.
Small, neutral refactoring to the CONNECT.START to make the subsequent commit easier. --- generator/states-connect.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/generator/states-connect.c b/generator/states-connect.c index 392879d..03b34c7 100644 --- a/generator/states-connect.c +++ b/generator/states-connect.c @@ -47,11 +47,12 @@ disable_nagle (int sock) STATE_MACHINE { CONNECT.START: - int fd; + sa_family_t family; + int fd, r; assert (!h->sock); - fd = socket (h->connaddr.ss_family, - SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); + family = h->connaddr.ss_family; + fd = socket (family, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); if (fd == -1) { SET_NEXT_STATE (%.DEAD); set_error (errno, "socket"); @@ -65,14 +66,12 @@ STATE_MACHINE { disable_nagle (fd); - if (connect (fd, (struct sockaddr *) &h->connaddr, - h->connaddrlen) == -1) { - if (errno != EINPROGRESS) { - SET_NEXT_STATE (%.DEAD); - set_error (errno, "connect"); - return 0; - } - } + r = connect (fd, (struct sockaddr *) &h->connaddr, h->connaddrlen); + if (r == 0 || (r == -1 && errno == EINPROGRESS)) + return 0; + assert (r == -1); + SET_NEXT_STATE (%.DEAD); + set_error (errno, "connect"); return 0; CONNECT.CONNECTING: -- 2.29.0.rc2
Richard W.M. Jones
2021-Feb-04 18:10 UTC
[Libguestfs] [PATCH libnbd 2/2] generator: Print a better error message if connect(2) returns EAGAIN.
The new error message is: nbd_connect_unix: connect: server backlog overflowed, see https://bugzilla.redhat.com/1925045: Resource temporarily unavailable Fixes: https://bugzilla.redhat.com/1925045 --- generator/states-connect.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/generator/states-connect.c b/generator/states-connect.c index 03b34c7..98c26e5 100644 --- a/generator/states-connect.c +++ b/generator/states-connect.c @@ -70,6 +70,22 @@ STATE_MACHINE { if (r == 0 || (r == -1 && errno == EINPROGRESS)) return 0; assert (r == -1); +#ifdef __linux__ + if (errno == EAGAIN && family == AF_UNIX) { + /* This can happen on Linux when connecting to a Unix domain + * socket, if the server's backlog is full. Unfortunately there + * is nothing good we can do on the client side when this happens + * since any solution would involve sleeping or busy-waiting. The + * only solution is on the server side, increasing the backlog. + * But at least improve the error message. + * https://bugzilla.redhat.com/1925045 + */ + SET_NEXT_STATE (%.DEAD); + set_error (errno, "connect: server backlog overflowed, " + "see https://bugzilla.redhat.com/1925045"); + return 0; + } +#endif SET_NEXT_STATE (%.DEAD); set_error (errno, "connect"); return 0; -- 2.29.0.rc2