aboutsummaryrefslogtreecommitdiffstats
path: root/iw_scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'iw_scan.c')
-rw-r--r--iw_scan.c56
1 files changed, 22 insertions, 34 deletions
diff --git a/iw_scan.c b/iw_scan.c
index 6426f68..2748376 100644
--- a/iw_scan.c
+++ b/iw_scan.c
@@ -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);