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