diff --git a/include/haproxy/pattern-t.h b/include/haproxy/pattern-t.h index aa3a17878..b84c7e71e 100644 --- a/include/haproxy/pattern-t.h +++ b/include/haproxy/pattern-t.h @@ -207,6 +207,7 @@ struct pattern_expr { struct eb_root pattern_tree; /* may be used for lookup in large datasets */ struct eb_root pattern_tree_2; /* may be used for different types */ int mflags; /* flags relative to the parsing or matching method. */ + uint32_t refcount; /* refcount used to know if the expr can be deleted or not */ __decl_thread(HA_RWLOCK_T lock); /* lock used to protect patterns */ }; @@ -216,7 +217,6 @@ struct pattern_expr { */ struct pattern_expr_list { struct list list; /* Used for chaining pattern_expr in pattern_head. */ - int do_free; struct pattern_expr *expr; /* The used expr. */ }; diff --git a/src/pattern.c b/src/pattern.c index 346fe59d5..7a2a15acc 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -2190,19 +2190,14 @@ struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref expr->ref = ref; HA_RWLOCK_INIT(&expr->lock); - - /* We must free this pattern if it is no more used. */ - list->do_free = 1; } else { - /* If the pattern used already exists, it is already linked - * with ref and we must not free it. - */ - list->do_free = 0; if (reuse) *reuse = 1; } + HA_ATOMIC_INC(&expr->refcount); + /* The new list element reference the pattern_expr. */ list->expr = expr; @@ -2583,7 +2578,7 @@ void pattern_prune(struct pattern_head *head) list_for_each_entry_safe(list, safe, &head->head, list) { LIST_DELETE(&list->list); - if (list->do_free) { + if (HA_ATOMIC_SUB_FETCH(&list->expr->refcount, 1) == 0) { LIST_DELETE(&list->expr->list); HA_RWLOCK_WRLOCK(PATEXP_LOCK, &list->expr->lock); head->prune(list->expr);