From 4fdc8def8855ce9b90ffbbdc47152ce46ccdcb1e Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Sat, 4 Aug 2012 20:34:27 +0300 Subject: [PATCH] Make UNIX socket non-blocking for ctrl_iface This keeps wpa_cli from hanging forever if the other end of the socket dies. Signed-hostap: Ben Greear --- src/common/wpa_ctrl.c | 40 ++++++++++++++++++++++++++++++++ wpa_supplicant/ctrl_iface_unix.c | 17 ++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c index b2b068323..2eac803e2 100644 --- a/src/common/wpa_ctrl.c +++ b/src/common/wpa_ctrl.c @@ -12,6 +12,8 @@ #ifdef CONFIG_CTRL_IFACE_UNIX #include +#include +#include #endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef ANDROID @@ -73,6 +75,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 +159,19 @@ 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); + if (flags >= 0) { + 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 +305,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 +332,30 @@ 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 a 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 7bebcb8bf..c106350e7 100644 --- a/wpa_supplicant/ctrl_iface_unix.c +++ b/wpa_supplicant/ctrl_iface_unix.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #ifdef ANDROID #include #endif /* ANDROID */ @@ -259,6 +261,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 +408,20 @@ 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); + if (flags >= 0) { + 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);