diff --git a/lib/core/context.c b/lib/core/context.c index 87668028c..ebc1fb84c 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -1851,7 +1851,7 @@ lws_check_deferred_free(struct lws_context *context, int tsi, int force) lws_context_lock(context, "check deferred free"); /* ------ context { */ - lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) { + lws_start_foreach_ll_safe(struct lws_vhost *, v, context->vhost_list, vhost_next) { if (v->being_destroyed #if LWS_MAX_SMP > 1 && !v->close_flow_vs_tsi[tsi] @@ -1882,7 +1882,7 @@ lws_check_deferred_free(struct lws_context *context, int tsi, int force) lws_pt_unlock(pt); /* } pt -------------- */ } - } lws_end_foreach_ll(v, vhost_next); + } lws_end_foreach_ll_safe(v); lws_context_unlock(context); /* } context ------------------- */ diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 622121a52..7bd9d4c76 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -5485,6 +5485,42 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, } \ } +/** + * lws_start_foreach_ll_safe(): linkedlist iterator helper start safe against delete + * + * \param type: type of iteration, eg, struct xyz * + * \param it: iterator var name to create + * \param start: start of list + * \param nxt: member name in the iterator pointing to next list element + * + * This helper creates an iterator and starts a while (it) { + * loop. The iterator runs through the linked list starting at start and + * ends when it gets a NULL. + * The while loop should be terminated using lws_end_foreach_ll_safe(). + * Performs storage of next increment for situations where iterator can become invalidated + * during iteration. + */ +#define lws_start_foreach_ll_safe(type, it, start, nxt)\ +{ \ + type it = start; \ + while (it) { \ + type next_##it = it->nxt; + +/** + * lws_end_foreach_ll_safe(): linkedlist iterator helper end (pre increment storage) + * + * \param it: same iterator var name given when starting + * + * This helper is the partner for lws_start_foreach_ll_safe() that ends the + * while loop. It uses the precreated next_ variable already stored during + * start. + */ + +#define lws_end_foreach_ll_safe(it) \ + it = next_##it; \ + } \ +} + /** * lws_start_foreach_llp(): linkedlist pointer iterator helper start *