diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-10-29 15:49:38 +0100 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2013-10-29 15:49:38 +0100 |
commit | a97db48a5cdd910f9fbcbc538044c473af36aaa3 (patch) | |
tree | 0bd58b225a37510d48aad4511c97ed30b2037fc5 | |
parent | 8656be5f44400ecb6e20b1044b7386765ee730db (diff) |
owfd: p2pd: catch race in wait_for_wpa()
If wpa_supplicant already opened the socket but is not ready to receive
events, yet, we need to continue trying. This is ugly, but stupid
SOCK_DGRAM leaves us no choice.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r-- | src/p2pd_interface.c | 57 |
1 files changed, 21 insertions, 36 deletions
diff --git a/src/p2pd_interface.c b/src/p2pd_interface.c index 9c84afb..6ed8880 100644 --- a/src/p2pd_interface.c +++ b/src/p2pd_interface.c @@ -107,7 +107,6 @@ static int wait_for_wpa(struct owfd_p2pd_interface *iface, int64_t t, start; struct pollfd fds[1]; char ev[sizeof(struct inotify_event) + 1024]; - struct inotify_event *e; struct timespec ts; /* create inotify-fd */ @@ -120,7 +119,6 @@ static int wait_for_wpa(struct owfd_p2pd_interface *iface, fds[0].fd = fd; fds[0].events = POLLHUP | POLLERR | POLLIN; -try_again: /* add /run/wpa_supplicant watch */ w = inotify_add_watch(fd, config->wpa_ctrldir, IN_CREATE | IN_MOVED_TO | IN_ONLYDIR); @@ -143,8 +141,9 @@ try_again: start = get_time_us(); fds[0].revents = 0; - /* poll for inotify events */ - us_to_timespec(&ts, t); + /* poll for inotify events; max 100ms per round */ + us_to_timespec(&ts, + (t > 100 * 1000LL) ? 100 * 1000LL : t); r = ppoll(fds, 1, &ts, mask); if (r < 0) { r = log_ERRNO(); @@ -156,6 +155,8 @@ try_again: /* update timeout */ t = t - (get_time_us() - start); + if (t < 0) + t = 0; /* verify wpa_supplicant is still alive */ if (!is_child_alive(iface->pid)) { @@ -209,8 +210,8 @@ try_again: start = get_time_us(); fds[0].revents = 0; - /* poll for events */ - us_to_timespec(&ts, t); + /* poll for events; max 100ms per round */ + us_to_timespec(&ts, (t > 100 * 1000LL) ? 100 * 1000LL : t); r = ppoll(fds, 1, &ts, mask); if (r < 0) { r = log_ERRNO(); @@ -222,6 +223,8 @@ try_again: /* update timeout */ t = t - (get_time_us() - start); + if (t < 0) + t = 0; /* verify wpa_supplicant is still alive */ if (!is_child_alive(iface->pid)) { @@ -230,26 +233,13 @@ try_again: goto err_close; } + /* retry opening socket */ + r = owfd_wpa_ctrl_open(iface->wpa, file, NULL); + if (r >= 0) + goto done; + /* drain input queue */ - r = read(fd, ev, sizeof(ev)); - if (r < 0 && errno != EAGAIN) { - r = log_ERRNO(); - goto err_close; - } else if (r > 0) { - e = (void*)ev; - if (e->wd == w) { - /* Yey! Startup should be clear now */ - if (e->mask & IN_OPEN) - break; - - /* Socket removed? Bail out and retry */ - if (e->mask & (IN_DELETE_SELF | - IN_MOVE_SELF | - IN_IGNORED | - IN_UNMOUNT)) - break; - } - } + read(fd, ev, sizeof(ev)); /* check for timeout and then continue polling */ if (t <= 0) { @@ -259,17 +249,6 @@ try_again: } } - /* remove directory watch */ - inotify_rm_watch(fd, w); - - /* retry opening socket */ - r = owfd_wpa_ctrl_open(iface->wpa, file, NULL); - if (r < 0) { - /* The ctrl-file may be a left-over of a previous start. Start - * all over again. */ - goto try_again; - } - done: r = 0; err_close: @@ -343,6 +322,12 @@ static void kill_wpa(struct owfd_p2pd_interface *iface) return; } + /* verify wpa_supplicant is still alive */ + if (!is_child_alive(iface->pid)) { + log_info("wpa_supplicant already exited"); + return; + } + log_error("cannot send termination request to wpa_supplicant (%d)", r); } |