summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-10-29 15:49:38 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2013-10-29 15:49:38 +0100
commita97db48a5cdd910f9fbcbc538044c473af36aaa3 (patch)
tree0bd58b225a37510d48aad4511c97ed30b2037fc5
parent8656be5f44400ecb6e20b1044b7386765ee730db (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.c57
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);
}