|SUCCESS| [RFC] eal: add destructor to unregister tailq on unload
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Thu Apr 23 00:33:48 CEST 2026
Test-Label: ai-code-review
Test-Status: SUCCESS
https://dpdk.org/patch/163238
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-04-22
Reviewing commit from series.patch:
git sha: 20260422205449.289861-1-stephen at networkplumber.org
Author: Stephen Hemminger <stephen at networkplumber.org>
Subject: [RFC] eal: add destructor to unregister tailq on unload
The patch adds cleanup for EAL_REGISTER_TAILQ to prevent dangling
pointers when libraries are unloaded via dlclose(). It introduces
rte_eal_tailq_unregister() and modifies the EAL_REGISTER_TAILQ macro to
emit an RTE_FINI destructor.
> diff --git a/lib/eal/common/eal_common_tailqs.c b/lib/eal/common/eal_common_tailqs.c
> index c581f43b6f..714f91d0ec 100644
> --- a/lib/eal/common/eal_common_tailqs.c
> +++ b/lib/eal/common/eal_common_tailqs.c
> @@ -148,6 +148,14 @@ rte_eal_tailq_register(struct rte_tailq_elem *t)
> return -1;
> }
>
> +RTE_EXPORT_SYMBOL(rte_eal_tailq_unregister)
> +void
> +rte_eal_tailq_unregister(struct rte_tailq_elem *t)
> +{
> + TAILQ_REMOVE(&rte_tailq_elem_head, t, next);
> + t->head = NULL;
> +}
Does this code need locking? The rte_eal_tailq_register() function
appears to use EAL_TAILQ_RWLOCK for consistency when accessing
rte_tailq_elem_head. Should rte_eal_tailq_unregister() acquire the same
lock around TAILQ_REMOVE()?
Can this code race during dlclose() if another thread is concurrently
traversing rte_tailq_elem_head via rte_eal_tailq_lookup() or similar?
> diff --git a/lib/eal/include/rte_tailq.h b/lib/eal/include/rte_tailq.h
> index e7caed6812..c5d5cb782f 100644
> --- a/lib/eal/include/rte_tailq.h
> +++ b/lib/eal/include/rte_tailq.h
> @@ -117,11 +117,28 @@ struct rte_tailq_head *rte_eal_tailq_lookup(const char *name);
> */
> int rte_eal_tailq_register(struct rte_tailq_elem *t);
>
> +/**
> + * Remove a tail queue element from the local list.
> + * This function is mainly used for EAL_REGISTER_TAILQ macro which pairs
> + * an RTE_FINI destructor with the existing RTE_INIT constructor.
> + * The destructor calls this function during dlclose() to prevent
> + * dangling pointers to unmapped library data.
> + *
> + * @param t
> + * The tailq element which contains the name of the tailq you want to
> + * delete
> + */
> +void rte_eal_tailq_unregister(struct rte_tailq_elem *t);
> +
> #define EAL_REGISTER_TAILQ(t) \
> RTE_INIT(tailqinitfn_ ##t) \
> { \
> if (rte_eal_tailq_register(&t) < 0) \
> rte_panic("Cannot initialize tailq: %s\n", t.name); \
> +} \
> +RTE_FINI(tailqfinifn_ ##t) \
> +{ \
> + rte_eal_tailq_unregister(&t); \
> }
Does this code handle cleanup of the tailq contents? The comment
mentions preventing dangling pointers to unmapped library data, but does
the destructor only remove the rte_tailq_elem from rte_tailq_elem_head,
or does it also handle the case where the actual tailq (pointed to by
t->head) may contain entries that should be freed?
Should the API documentation warn about ordering guarantees during
unload? If library A depends on library B and both register tailqs, can
the unload order cause B's destructor to run while A still references
data in B's tailq?
Does rte_eal_tailq_unregister() need an @experimental tag since this is
new API in an RFC patch, or does the commit indicate it should be stable
immediately?
More information about the test-report
mailing list