void *eloop_data;
void *user_data;
eloop_sock_handler handler;
+ WPA_TRACE_REF(eloop);
+ WPA_TRACE_REF(user);
WPA_TRACE_INFO
};
void *eloop_data;
void *user_data;
eloop_timeout_handler handler;
+ WPA_TRACE_REF(eloop);
+ WPA_TRACE_REF(user);
WPA_TRACE_INFO
};
#ifdef WPA_TRACE
+
static void eloop_sigsegv_handler(int sig)
{
wpa_trace_show("eloop SIGSEGV");
abort();
}
+
+static void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
+{
+ int i;
+ if (table == NULL || table->table == NULL)
+ return;
+ for (i = 0; i < table->count; i++) {
+ wpa_trace_add_ref(&table->table[i], eloop,
+ table->table[i].eloop_data);
+ wpa_trace_add_ref(&table->table[i], user,
+ table->table[i].user_data);
+ }
+}
+
+
+static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
+{
+ int i;
+ if (table == NULL || table->table == NULL)
+ return;
+ for (i = 0; i < table->count; i++) {
+ wpa_trace_remove_ref(&table->table[i], eloop,
+ table->table[i].eloop_data);
+ wpa_trace_remove_ref(&table->table[i], user,
+ table->table[i].user_data);
+ }
+}
+
+#else /* WPA_TRACE */
+
+#define eloop_trace_sock_add_ref(table) do { } while (0)
+#define eloop_trace_sock_remove_ref(table) do { } while (0)
+
#endif /* WPA_TRACE */
if (table == NULL)
return -1;
+ eloop_trace_sock_remove_ref(table);
tmp = (struct eloop_sock *)
os_realloc(table->table,
(table->count + 1) * sizeof(struct eloop_sock));
if (sock > eloop.max_sock)
eloop.max_sock = sock;
table->changed = 1;
+ eloop_trace_sock_add_ref(table);
return 0;
}
}
if (i == table->count)
return;
+ eloop_trace_sock_remove_ref(table);
if (i != table->count - 1) {
os_memmove(&table->table[i], &table->table[i + 1],
(table->count - i - 1) *
}
table->count--;
table->changed = 1;
+ eloop_trace_sock_add_ref(table);
}
timeout->eloop_data = eloop_data;
timeout->user_data = user_data;
timeout->handler = handler;
+ wpa_trace_add_ref(timeout, eloop, eloop_data);
+ wpa_trace_add_ref(timeout, user, user_data);
wpa_trace_record(timeout);
/* Maintain timeouts in order of increasing time */
}
+static void eloop_remove_timeout(struct eloop_timeout *timeout)
+{
+ wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
+ wpa_trace_remove_ref(timeout, user, timeout->user_data);
+ os_free(timeout);
+}
+
+
int eloop_cancel_timeout(eloop_timeout_handler handler,
void *eloop_data, void *user_data)
{
(timeout->user_data == user_data ||
user_data == ELOOP_ALL_CTX)) {
dl_list_del(&timeout->list);
- os_free(timeout);
+ eloop_remove_timeout(timeout);
removed++;
}
}
dl_list_del(&timeout->list);
timeout->handler(timeout->eloop_data,
timeout->user_data);
- os_free(timeout);
+ eloop_remove_timeout(timeout);
}
}
sec, usec, timeout->eloop_data, timeout->user_data,
timeout->handler);
wpa_trace_dump("eloop timeout", timeout);
- os_free(timeout);
+ dl_list_del(&timeout->list);
+ eloop_remove_timeout(timeout);
}
eloop_sock_table_destroy(&eloop.readers);
eloop_sock_table_destroy(&eloop.writers);
#ifdef WPA_TRACE
+static struct dl_list active_references =
+{ &active_references, &active_references };
+
#ifdef WPA_TRACE_BFD
#include <bfd.h>
#include <demangle.h>
wpa_trace_dump(title, &info);
}
+
+void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr)
+{
+ if (addr == NULL)
+ return;
+ ref->addr = addr;
+ wpa_trace_record(ref);
+ dl_list_add(&active_references, &ref->list);
+}
+
+
+void wpa_trace_check_ref(const void *addr)
+{
+ struct wpa_trace_ref *ref;
+ dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) {
+ if (addr != ref->addr)
+ continue;
+ wpa_trace_show("Freeing referenced memory");
+ wpa_trace_dump("Reference registration", ref);
+ abort();
+ }
+}
+
#endif /* WPA_TRACE */
#ifdef WPA_TRACE
#include <execinfo.h>
+#include "list.h"
+
#define WPA_TRACE_INFO void *btrace[WPA_TRACE_LEN]; int btrace_num;
+
+struct wpa_trace_ref {
+ struct dl_list list;
+ const void *addr;
+ WPA_TRACE_INFO
+};
+#define WPA_TRACE_REF(name) struct wpa_trace_ref wpa_trace_ref_##name
+
#define wpa_trace_dump(title, ptr) \
wpa_trace_dump_func((title), (ptr)->btrace, (ptr)->btrace_num)
void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num);
#define wpa_trace_record(ptr) \
(ptr)->btrace_num = backtrace((ptr)->btrace, WPA_TRACE_LEN)
void wpa_trace_show(const char *title);
+#define wpa_trace_add_ref(ptr, name, addr) \
+ wpa_trace_add_ref_func(&(ptr)->wpa_trace_ref_##name, (addr))
+void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr);
+#define wpa_trace_remove_ref(ptr, name, addr) \
+ do { \
+ if ((addr)) \
+ dl_list_del(&(ptr)->wpa_trace_ref_##name.list); \
+ } while (0)
+void wpa_trace_check_ref(const void *addr);
#else /* WPA_TRACE */
#define WPA_TRACE_INFO
+#define WPA_TRACE_REF(n)
#define wpa_trace_dump(title, ptr) do { } while (0)
#define wpa_trace_record(ptr) do { } while (0)
#define wpa_trace_show(title) do { } while (0)
+#define wpa_trace_add_ref(ptr, name, addr) do { } while (0)
+#define wpa_trace_remove_ref(ptr, name, addr) do { } while (0)
+#define wpa_trace_check_ref(addr) do { } while (0)
#endif /* WPA_TRACE */