Patchwork [1/3] supplicant: Make unix socket non-blocking.

login
register
mail settings
Submitter Ben Greear
Date April 6, 2012, 11:04 p.m.
Message ID <1333753454-21306-1-git-send-email-greearb@candelatech.com>
Download mbox | patch
Permalink /patch/151281/
State Superseded
Headers show

Comments

Ben Greear - April 6, 2012, 11:04 p.m.
From: Ben Greear <greearb@candelatech.com>

This keeps wpa_cli from hanging forever if the other end of the
socket dies.

Signed-hostap: Ben Greear <greearb@candelatech.com>
---
:100644 100644 b2b0683... e671f79... M	src/common/wpa_ctrl.c
:100644 100644 7bebcb8... e4fc6bb... M	wpa_supplicant/ctrl_iface_unix.c
 src/common/wpa_ctrl.c            |   37 ++++++++++++++++++++++++++++++++++++-
 wpa_supplicant/ctrl_iface_unix.c |   15 ++++++++++++++-
 2 files changed, 50 insertions(+), 2 deletions(-)

Patch

diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
index b2b0683..e671f79 100644
--- a/src/common/wpa_ctrl.c
+++ b/src/common/wpa_ctrl.c
@@ -12,6 +12,8 @@ 
 
 #ifdef CONFIG_CTRL_IFACE_UNIX
 #include <sys/un.h>
+#include <unistd.h>
+#include <fcntl.h>
 #endif /* CONFIG_CTRL_IFACE_UNIX */
 
 #ifdef ANDROID
@@ -23,7 +25,6 @@ 
 #include "wpa_ctrl.h"
 #include "common.h"
 
-
 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
 #define CTRL_IFACE_SOCKET
 #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
@@ -73,6 +74,7 @@  struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
 	int ret;
 	size_t res;
 	int tries = 0;
+	int flags;
 
 	ctrl = os_malloc(sizeof(*ctrl));
 	if (ctrl == NULL)
@@ -156,6 +158,16 @@  try_again:
 		return NULL;
 	}
 
+	/* Make socket non-blocking so that we don't hang forever if
+	 * target dies unexpectedly.
+	 */
+	flags = fcntl(ctrl->s, F_GETFL);
+	flags |= (O_NONBLOCK);
+	if (fcntl(ctrl->s, F_SETFL, flags) < 0) {
+		perror("fcntl(ctrl->s, O_NONBLOCK)");
+		/* Not fatal, continue on.*/
+	}
+
 	return ctrl;
 }
 
@@ -289,6 +301,7 @@  int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
 		     void (*msg_cb)(char *msg, size_t len))
 {
 	struct timeval tv;
+	struct os_time started_at;
 	int res;
 	fd_set rfds;
 	const char *_cmd;
@@ -315,7 +328,29 @@  int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
 		_cmd_len = cmd_len;
 	}
 
+	errno = 0;
+	started_at.sec = 0;
+	started_at.usec = 0;
+retry_send:
 	if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
+		if ((errno == EAGAIN) || (errno = EBUSY)
+		    || (errno == EWOULDBLOCK)) {
+			/* Must be non-blocking socket...try for a bit longer
+			 * before giving up.
+			 */
+			if (started_at.sec == 0)
+				os_get_time(&started_at);
+			else {
+				struct os_time n;
+				os_get_time(&n);
+				/* Try for a few seconds. */
+				if (n.sec > (started_at.sec + 5))
+					goto send_err;
+			}
+			os_sleep(1, 0);
+			goto retry_send;
+		}
+	send_err:
 		os_free(cmd_buf);
 		return -1;
 	}
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 7bebcb8..e4fc6bb 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -14,7 +14,8 @@ 
 #ifdef ANDROID
 #include <cutils/sockets.h>
 #endif /* ANDROID */
-
+#include <unistd.h>
+#include <fcntl.h>
 #include "utils/common.h"
 #include "utils/eloop.h"
 #include "utils/list.h"
@@ -259,6 +260,7 @@  wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
 	char *buf, *dir = NULL, *gid_str = NULL;
 	struct group *grp;
 	char *endp;
+	int  flags;
 
 	priv = os_zalloc(sizeof(*priv));
 	if (priv == NULL)
@@ -405,6 +407,17 @@  wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
 #ifdef ANDROID
 havesock:
 #endif /* ANDROID */
+
+	/* Make socket non-blocking so that we don't hang forever if
+	 * target dies unexpectedly.
+	 */
+	flags = fcntl(priv->sock, F_GETFL);
+	flags |= (O_NONBLOCK);
+	if (fcntl(priv->sock, F_SETFL, flags) < 0) {
+		perror("fcntl(ctrl, O_NONBLOCK)");
+		/* Not fatal, continue on.*/
+	}
+
 	eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
 				 wpa_s, priv);
 	wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);