diff options
Diffstat (limited to '')
-rw-r--r-- | iw_scan.c | 56 |
1 files changed, 22 insertions, 34 deletions
@@ -105,7 +105,7 @@ static int wait_event(struct nl_msg *msg, void *arg) * Returns true if scan results are available, false if scan was aborted. * Taken from iw:event.c:__do_listen_events */ -static bool wait_for_scan_events(struct scan_result *sr) +static bool wait_for_scan_events(void) { static const uint32_t cmds[] = { NL80211_CMD_NEW_SCAN_RESULTS, @@ -293,7 +293,8 @@ void sort_scan_list(struct scan_entry **headp) *headp = head; } -static void free_scan_list(struct scan_entry *head) +/** De-allocate list. Use after all threads are terminated. */ +void free_scan_list(struct scan_entry *head) { if (head) { free_scan_list(head->next); @@ -301,9 +302,9 @@ static void free_scan_list(struct scan_entry *head) } } -static void clear_scan_list(struct scan_result *sr) +/** Initialize scan results. Requires lock to be taken. */ +void init_scan_list(struct scan_result *sr) { - pthread_mutex_lock(&sr->mutex); free_scan_list(sr->head); free(sr->channel_stats); sr->head = NULL; @@ -311,7 +312,7 @@ static void clear_scan_list(struct scan_result *sr) sr->msg[0] = '\0'; sr->max_essid_len = MAX_ESSID_LEN; memset(&(sr->num), 0, sizeof(sr->num)); - pthread_mutex_unlock(&sr->mutex); + sr->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; } /* @@ -366,28 +367,6 @@ static void compute_channel_stats(struct scan_result *sr) sr->num.ch_stats = n < MAX_CH_STATS ? n : MAX_CH_STATS; } -/* - * Scan results. - */ -void scan_result_init(struct scan_result *sr) -{ - pthread_mutexattr_t ma; - - memset(sr, 0, sizeof(*sr)); - pthread_mutexattr_init(&ma); - if (pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST) < 0) - err_sys("Failed to set the mutex robust attribute"); - pthread_mutex_init(&sr->mutex, &ma); -} - -void scan_result_fini(struct scan_result *sr) -{ - /* FIXME: this may have a bug on resource de-allocation, if the main thread still holds the lock */ - free_scan_list(sr->head); - free(sr->channel_stats); - pthread_mutex_destroy(&sr->mutex); -} - /** The actual scan thread. */ void *do_scan(void *sr_ptr) { @@ -402,15 +381,21 @@ void *do_scan(void *sr_ptr) pthread_detach(pthread_self()); do { - clear_scan_list(sr); - ret = iw_nl80211_scan_trigger(); + + pthread_mutex_lock(&sr->mutex); + init_scan_list(sr); switch(-ret) { case 0: case EBUSY: /* Trigger returns -EBUSY if a scan request is pending or ready. */ - if (!wait_for_scan_events(sr)) { + pthread_mutex_unlock(&sr->mutex); + + /* Do not hold the lock while awaiting results. */ + if (!wait_for_scan_events()) { + pthread_mutex_lock(&sr->mutex); snprintf(sr->msg, sizeof(sr->msg), "Waiting for scan data..."); + pthread_mutex_unlock(&sr->mutex); } else { pthread_mutex_lock(&sr->mutex); ret = iw_nl80211_get_scan_data(sr); @@ -426,8 +411,8 @@ void *do_scan(void *sr_ptr) break; case EPERM: if (!has_net_admin_capability()) - snprintf(sr->msg, sizeof(sr->msg), - "This screen requires CAP_NET_ADMIN permissions"); + snprintf(sr->msg, sizeof(sr->msg), "This screen requires CAP_NET_ADMIN permissions"); + pthread_mutex_unlock(&sr->mutex); return NULL; case EFAULT: /* EFAULT can occur after a window resizing event: temporary, fall through. */ @@ -435,18 +420,21 @@ void *do_scan(void *sr_ptr) case EAGAIN: /* Temporary errors. */ snprintf(sr->msg, sizeof(sr->msg), "Waiting for device to become ready ..."); + pthread_mutex_unlock(&sr->mutex); break; case ENETDOWN: if (!if_is_up(conf_ifname())) { snprintf(sr->msg, sizeof(sr->msg), "Interface %s is down - setting it up ...", conf_ifname()); + pthread_mutex_unlock(&sr->mutex); + if (if_set_up(conf_ifname()) < 0) err_sys("Can not bring up interface '%s'", conf_ifname()); break; } /* fall through */ default: - snprintf(sr->msg, sizeof(sr->msg), - "Scan trigger failed on %s: %s", conf_ifname(), strerror(-ret)); + snprintf(sr->msg, sizeof(sr->msg), "Scan trigger failed on %s: %s", conf_ifname(), strerror(-ret)); + pthread_mutex_unlock(&sr->mutex); } } while (usleep(conf.stat_iv * 1000) == 0); |