struct queue *notify_list;
unsigned int next_request_id;
unsigned int next_notify_id;
+ bool need_notify_cleanup;
+ bool in_notify;
void *buf;
uint16_t len;
mgmt_debug_func_t debug_callback;
unsigned int id;
uint16_t event;
uint16_t index;
+ bool removed;
mgmt_notify_func_t callback;
mgmt_destroy_func_t destroy;
void *user_data;
return notify->index == index;
}
+static bool match_notify_removed(const void *a, const void *b)
+{
+ const struct mgmt_notify *notify = a;
+
+ return notify->removed;
+}
+
+static void mark_notify_removed(void *data , void *user_data)
+{
+ struct mgmt_notify *notify = data;
+ uint16_t index = PTR_TO_UINT(user_data);
+
+ if (notify->index == index || index == MGMT_INDEX_NONE)
+ notify->removed = true;
+}
+
static void write_watch_destroy(void *user_data)
{
struct mgmt *mgmt = user_data;
struct mgmt_notify *notify = data;
struct event_index *match = user_data;
+ if (notify->removed)
+ return;
+
if (notify->event != match->event)
return;
struct event_index match = { .event = event, .index = index,
.length = length, .param = param };
+ mgmt->in_notify = true;
+
queue_foreach(mgmt->notify_list, notify_handler, &match);
+
+ mgmt->in_notify = false;
+
+ if (mgmt->need_notify_cleanup) {
+ queue_remove_all(mgmt->notify_list, match_notify_removed,
+ NULL, destroy_notify);
+ mgmt->need_notify_cleanup = false;
+ }
}
static bool can_read_data(struct io *io, void *user_data)
free(mgmt->buf);
mgmt->buf = NULL;
- queue_destroy(mgmt->notify_list, NULL);
- queue_destroy(mgmt->pending_list, NULL);
- free(mgmt);
-
- return;
+ if (!mgmt->in_notify) {
+ queue_destroy(mgmt->notify_list, NULL);
+ queue_destroy(mgmt->pending_list, NULL);
+ free(mgmt);
+ return;
+ }
}
bool mgmt_set_debug(struct mgmt *mgmt, mgmt_debug_func_t callback,
if (!notify)
return false;
- destroy_notify(notify);
+ if (!mgmt->in_notify) {
+ destroy_notify(notify);
+ return true;
+ }
+
+ notify->removed = true;
+ mgmt->need_notify_cleanup = true;
+
return true;
}
if (!mgmt)
return false;
- queue_remove_all(mgmt->notify_list, match_notify_index,
+ if (mgmt->in_notify) {
+ queue_foreach(mgmt->notify_list, mark_notify_removed,
+ UINT_TO_PTR(index));
+ mgmt->need_notify_cleanup = true;
+ } else
+ queue_remove_all(mgmt->notify_list, match_notify_index,
UINT_TO_PTR(index), destroy_notify);
return true;
if (!mgmt)
return false;
- queue_remove_all(mgmt->notify_list, NULL, NULL, destroy_notify);
+ if (mgmt->in_notify) {
+ queue_foreach(mgmt->notify_list, mark_notify_removed,
+ UINT_TO_PTR(MGMT_INDEX_NONE));
+ mgmt->need_notify_cleanup = true;
+ } else
+ queue_remove_all(mgmt->notify_list, NULL, NULL, destroy_notify);
return true;
}