Blob Blame Raw
From d2d3940a65dab60a2caeaf824eaff12fcc85e1f0 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 12 Sep 2019 10:28:19 +0100
Subject: [PATCH 2/3] nbd_connect_tcp: Try to return errno from underlying
 connect(2) call.

When we make a TCP connection we have to make multiple underlying
connect(2) calls, once for each address returned by getaddrinfo.
Unfortunately this meant that we lost the errno from any of these
calls:

$ nbdsh -c 'h.connect_tcp ("localhost", "nbd")'
nbd.Error: nbd_connect_tcp: connect: localhost:nbd: could not connect to remote host

This commit saves the errno from the first failed connect(2):

$ ./run nbdsh -c 'h.connect_tcp ("localhost", "nbd")'
nbd.Error: nbd_connect_tcp: connect: localhost:nbd: could not connect to remote host: Connection refused (ECONNREFUSED)
---
 generator/states-connect.c | 12 ++++++++++--
 lib/internal.h             |  1 +
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/generator/states-connect.c b/generator/states-connect.c
index 9e2e1d4..e9b3582 100644
--- a/generator/states-connect.c
+++ b/generator/states-connect.c
@@ -128,6 +128,8 @@ disable_nagle (int sock)
     h->result = NULL;
   }
 
+  h->connect_errno = 0;
+
   memset (&h->hints, 0, sizeof h->hints);
   h->hints.ai_family = AF_UNSPEC;
   h->hints.ai_socktype = SOCK_STREAM;
@@ -160,7 +162,8 @@ disable_nagle (int sock)
      * Save errno from most recent connect(2) call. XXX
      */
     SET_NEXT_STATE (%^START);
-    set_error (0, "connect: %s:%s: could not connect to remote host",
+    set_error (h->connect_errno,
+               "connect: %s:%s: could not connect to remote host",
                h->hostname, h->port);
     return -1;
   }
@@ -182,6 +185,8 @@ disable_nagle (int sock)
 
   if (connect (fd, h->rp->ai_addr, h->rp->ai_addrlen) == -1) {
     if (errno != EINPROGRESS) {
+      if (h->connect_errno == 0)
+        h->connect_errno = errno;
       SET_NEXT_STATE (%NEXT_ADDRESS);
       return 0;
     }
@@ -203,8 +208,11 @@ disable_nagle (int sock)
   /* This checks the status of the original connect call. */
   if (status == 0)
     SET_NEXT_STATE (%^MAGIC.START);
-  else
+  else {
+    if (h->connect_errno == 0)
+      h->connect_errno = status;
     SET_NEXT_STATE (%NEXT_ADDRESS);
+  }
   return 0;
 
  CONNECT_TCP.NEXT_ADDRESS:
diff --git a/lib/internal.h b/lib/internal.h
index a48edff..ccaca32 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -188,6 +188,7 @@ struct nbd_handle {
   char *hostname, *port;
   struct addrinfo hints;
   struct addrinfo *result, *rp;
+  int connect_errno;
 
   /* When sending metadata contexts, this is used. */
   size_t querynum;
-- 
2.23.0