I also made the code a bit more robust about closing the socket along
error paths.
---
generator/states-connect.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/generator/states-connect.c b/generator/states-connect.c
index ba8b240..a69b70f 100644
--- a/generator/states-connect.c
+++ b/generator/states-connect.c
@@ -27,6 +27,7 @@
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
@@ -183,12 +184,12 @@
CONNECT_COMMAND.START:
int sv[2];
pid_t pid;
+ int flags;
assert (!h->sock);
assert (h->argv);
assert (h->argv[0]);
- if (socketpair (AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0,
- sv) == -1) {
+ if (socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv) == -1) {
SET_NEXT_STATE (%.DEAD);
set_error (errno, "socketpair");
return -1;
@@ -219,13 +220,27 @@
}
/* Parent. */
+ close (sv[1]);
+
h->pid = pid;
+
+ /* The socket must be set to non-blocking only in the parent,
+ * because the child may not be expecting a non-blocking socket.
+ */
+ flags = fcntl (sv[0], F_GETFL, 0);
+ if (flags == -1 ||
+ fcntl (sv[0], F_SETFL, flags|O_NONBLOCK) == -1) {
+ SET_NEXT_STATE (%.DEAD);
+ close (sv[0]);
+ return -1;
+ }
+
h->sock = nbd_internal_socket_create (sv[0]);
if (!h->sock) {
SET_NEXT_STATE (%.DEAD);
+ close (sv[0]);
return -1;
}
- close (sv[1]);
/* The sockets are connected already, we can jump directly to
* receiving the server magic.
--
2.21.0