aboutsummaryrefslogtreecommitdiffstats
path: root/src/common/wpa_ctrl.c
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2012-08-04 17:34:27 (GMT)
committerJouni Malinen <j@w1.fi>2012-08-04 17:34:27 (GMT)
commit4fdc8def8855ce9b90ffbbdc47152ce46ccdcb1e (patch)
tree5fc838620fe28f9a3b673d17d78bc6a050759fd5 /src/common/wpa_ctrl.c
parentc8b245b6a413c427e94486221489eebaad719739 (diff)
downloadhostap-4fdc8def8855ce9b90ffbbdc47152ce46ccdcb1e.zip
hostap-4fdc8def8855ce9b90ffbbdc47152ce46ccdcb1e.tar.gz
hostap-4fdc8def8855ce9b90ffbbdc47152ce46ccdcb1e.tar.bz2
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 <greearb@candelatech.com>
Diffstat (limited to 'src/common/wpa_ctrl.c')
-rw-r--r--src/common/wpa_ctrl.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
index b2b0683..2eac803 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
@@ -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;
}