diff options
author | Wim Taymans <wtaymans@redhat.com> | 2018-05-17 17:21:30 +0200 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2018-06-15 13:11:00 +0200 |
commit | 1e54d9e00bd29369abd6b96536304d370a777960 (patch) | |
tree | 2984378d690dbc1ec8b86e47ea57b64a82f4736c /spa | |
parent | 85f81ab4e2178db9aab31887835faab65c4adbb8 (diff) |
hook: make safer
Also protect against removal of the next hook by using a cursor.
Diffstat (limited to 'spa')
-rw-r--r-- | spa/include/spa/utils/hook.h | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/spa/include/spa/utils/hook.h b/spa/include/spa/utils/hook.h index 97bda859..8fddc252 100644 --- a/spa/include/spa/utils/hook.h +++ b/spa/include/spa/utils/hook.h @@ -80,20 +80,28 @@ static inline void spa_hook_remove(struct spa_hook *hook) /** Call all hooks in a list, starting from the given one and optionally stopping * after calling the first non-NULL function, returns the number of methods * called */ -#define spa_hook_list_do_call(l,start,type,method,once,...) ({ \ +#define spa_hook_list_do_call(l,start,type,method,once,...) \ +({ \ struct spa_hook_list *list = l; \ struct spa_list *s = start ? (struct spa_list *)start : &list->list; \ - struct spa_hook *ci, *t; \ + struct spa_hook cursor = { 0, }; \ + struct spa_hook *ci; \ int count = 0; \ - spa_list_for_each_safe_next(ci, t, &list->list, s, link) { \ + spa_list_prepend(s, &cursor.link); \ + for(ci = spa_list_first(&cursor.link, struct spa_hook, link); \ + &ci->link != s; \ + ci = spa_list_next(&cursor, link)) { \ const type *cb = ci->funcs; \ - if (cb->method) { \ + spa_list_remove(&ci->link); \ + spa_list_append(&cursor.link, &ci->link); \ + if (cb && cb->method) { \ cb->method(ci->data, ## __VA_ARGS__); \ count++; \ if (once) \ break; \ } \ } \ + spa_list_remove(&cursor.link); \ count; \ }) |