diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 923fc0b50609..22f78fb80a93 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -110,6 +110,8 @@ struct rpki_vrf { QOBJ_FIELDS; }; +static pthread_key_t rpki_pthread; + static struct rpki_vrf *find_rpki_vrf(const char *vrfname); static int bgp_rpki_vrf_update(struct vrf *vrf, bool enabled); static int bgp_rpki_write_vrf(struct vty *vty, struct vrf *vrf); @@ -887,6 +889,8 @@ static int bgp_rpki_fini(void) static int bgp_rpki_module_init(void) { + pthread_key_create(&rpki_pthread, NULL); + lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper); hook_register(bgp_rpki_prefix_status, rpki_validate_prefix); @@ -1297,11 +1301,35 @@ static int rpki_create_socket(void *_cache) rpki_vrf = cache->rpki_vrf; - if (frr_pthread_non_controlled_startup(cache->rtr_socket->thread_id, + /* + * the rpki infrastructure can call this function + * multiple times per pthread. Why? I have absolutely + * no idea, and I am not sure I care a whole bunch. + * Why does this matter? Well when we attempt to + * hook this pthread into the rcu structure multiple + * times the rcu code asserts on shutdown. Clearly + * upset that you have rcu data associated with a pthread + * that has not been cleaned up. And frankly this is rightly so. + * + * At this point we know that this function is not + * called a million bajillion times so let's just + * add a bit of insurance by looking to see if + * some thread specific code has been set for this + * pthread. If not, hook into the rcu code and + * make things happy. + * + * IF YOU PUT A ZLOG_XXXX prior to the call into + * frr_pthread_non_controlled_startup in this function + * BGP WILL CRASH. You have been warned. + */ + if (!pthread_getspecific(rpki_pthread) && + frr_pthread_non_controlled_startup(cache->rtr_socket->thread_id, "RPKI RTRLIB socket", "rpki_create_socket") < 0) return -1; + pthread_setspecific(rpki_pthread, &rpki_pthread); + if (rpki_vrf->vrfname == NULL) vrf = vrf_lookup_by_id(VRF_DEFAULT); else diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index f7e57136d607..1ffa5934aa5b 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -234,6 +234,10 @@ static void *frr_pthread_attr_non_controlled_start(void *arg) int frr_pthread_non_controlled_startup(pthread_t thread, const char *name, const char *os_name) { + struct rcu_thread *rcu_thread = rcu_thread_new(NULL); + + rcu_thread_start(rcu_thread); + struct frr_pthread_attr attr = { .start = frr_pthread_attr_non_controlled_start, .stop = frr_pthread_attr_default.stop, @@ -245,7 +249,7 @@ int frr_pthread_non_controlled_startup(pthread_t thread, const char *name, return -1; fpt->thread = thread; - fpt->rcu_thread = rcu_thread_new(NULL); + fpt->rcu_thread = rcu_thread; frr_pthread_inner(fpt); return 0;