On Sun, 7 Jun 2026 at 17:04, Stephen Hemminger <[email protected]> wrote: > > Libraries that use EAL_REGISTER_TAILQ insert a pointer to a static > struct rte_tailq_elem into the process-local tailq list via a > constructor, but have no matching destructor. When such a library > is loaded as a dependency of a plugin via dlopen() and later > unloaded via dlclose(), the list retains a dangling pointer to the > now-unmapped static. Reloading the plugin crashes in > rte_eal_tailq_local_register() when it traverses the stale entry. > > Add rte_eal_tailq_unregister() and extend the EAL_REGISTER_TAILQ > macro to emit an RTE_FINI destructor alongside the existing > RTE_INIT constructor. Every library that uses the macro > automatically gets both sides; no per-library changes are needed. > > Bugzilla ID: 1081 > Fixes: 873a61c7526b ("tailq: introduce dynamic register system") > Cc: [email protected] > > Signed-off-by: Stephen Hemminger <[email protected]> > --- > lib/eal/common/eal_common_tailqs.c | 8 ++++++++ > lib/eal/include/rte_tailq.h | 17 +++++++++++++++++ > 2 files changed, 25 insertions(+) > > 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; > +}
This cleans up the local storage which is good, but it leaves an entry reserved in the mcfg->tailq_head[] array. -- David Marchand

