watchlist: Save the watchlist pointer in WATCHLIST_NOTIFY_*

Save the value of the watchlist pointer at the beginning of the
WATCHLIST_NOTIFY_* macros as if it was a function.  This will fix a
frame-xchg.c scenario in which one of the watch callback removes the
frame watch group and the memory where the watchlist pointer was
becomes unallocated but the macro still needs to access it ones or
twice while it destroys the watchlist.  Another option would be for
the pointer to be copied in frame-xchg.c itself.
This commit is contained in:
Andrew Zaborowski 2020-04-30 15:48:44 +02:00 committed by Denis Kenzior
parent c49b724a2e
commit 7711b06b6b
1 changed files with 24 additions and 21 deletions

View File

@ -58,34 +58,36 @@ void watchlist_free(struct watchlist *watchlist);
void __watchlist_prune_stale(struct watchlist *watchlist);
#define WATCHLIST_NOTIFY(watchlist, type, args...) \
#define WATCHLIST_NOTIFY(list, type, args...) \
do { \
struct watchlist *watchlist = (list); \
const struct l_queue_entry *entry = \
l_queue_get_entries((watchlist)->items);\
l_queue_get_entries(watchlist->items); \
\
(watchlist)->in_notify = true; \
watchlist->in_notify = true; \
for (; entry; entry = entry->next) { \
struct watchlist_item *item = entry->data; \
type t = item->notify; \
if (item->id == 0) \
continue; \
t(args, item->notify_data); \
if ((watchlist)->pending_destroy) \
if (watchlist->pending_destroy) \
break; \
} \
(watchlist)->in_notify = false; \
if ((watchlist)->pending_destroy) \
watchlist->in_notify = false; \
if (watchlist->pending_destroy) \
watchlist_destroy(watchlist); \
else if ((watchlist)->stale_items) \
else if (watchlist->stale_items) \
__watchlist_prune_stale(watchlist); \
} while (false) \
#define WATCHLIST_NOTIFY_MATCHES(watchlist, match, match_data, type, args...) \
#define WATCHLIST_NOTIFY_MATCHES(list, match, match_data, type, args...) \
do { \
struct watchlist *watchlist = (list); \
const struct l_queue_entry *entry = \
l_queue_get_entries((watchlist)->items);\
l_queue_get_entries(watchlist->items); \
\
(watchlist)->in_notify = true; \
watchlist->in_notify = true; \
for (; entry; entry = entry->next) { \
struct watchlist_item *item = entry->data; \
type t = item->notify; \
@ -97,34 +99,35 @@ void __watchlist_prune_stale(struct watchlist *watchlist);
\
t(args, item->notify_data); \
\
if ((watchlist)->pending_destroy) \
if (watchlist->pending_destroy) \
break; \
} \
(watchlist)->in_notify = false; \
if ((watchlist)->pending_destroy) \
watchlist->in_notify = false; \
if (watchlist->pending_destroy) \
watchlist_destroy(watchlist); \
else if ((watchlist)->stale_items) \
else if (watchlist->stale_items) \
__watchlist_prune_stale(watchlist); \
} while (false)
#define WATCHLIST_NOTIFY_NO_ARGS(watchlist, type) \
#define WATCHLIST_NOTIFY_NO_ARGS(list, type) \
do { \
struct watchlist *watchlist = (list); \
const struct l_queue_entry *entry = \
l_queue_get_entries((watchlist)->items);\
l_queue_get_entries(watchlist->items); \
\
(watchlist)->in_notify = true; \
watchlist->in_notify = true; \
for (; entry; entry = entry->next) { \
struct watchlist_item *item = entry->data; \
type t = item->notify; \
if (item->id == 0) \
continue; \
t(item->notify_data); \
if ((watchlist)->pending_destroy) \
if (watchlist->pending_destroy) \
break; \
} \
(watchlist)->in_notify = false; \
if ((watchlist)->pending_destroy) \
watchlist->in_notify = false; \
if (watchlist->pending_destroy) \
watchlist_destroy(watchlist); \
else if ((watchlist)->stale_items) \
else if (watchlist->stale_items) \
__watchlist_prune_stale(watchlist); \
} while (false)