Commit 04ac7e0e37 for frr
commit 04ac7e0e3771bd6931c317f1d7f65a12536f7fa9
Author: Donald Sharp <sharpd@nvidia.com>
Date: Mon Oct 5 19:24:41 2026 -0400
lib: Fix crash in event.c on FreeBSD
lib/event.c is crashing on freebsd in bgpd:
6 0x0000000828503fda in thr_kill () from /lib/libsys.so.7
7 0x000000082633ae74 in raise () from /lib/libc.so.7
8 0x00000008263edb29 in abort () from /lib/libc.so.7
9 0x000000082591cbea in ?? () from /lib/libthr.so.3
10 0x00000008259212d5 in ?? () from /lib/libthr.so.3
11 0x0000000825920461 in pthread_mutex_lock () from /lib/libthr.so.3
12 0x00000008216b585a in _frr_mtx_lock (mutex=0xdc2a0408978) at lib/frr_pthread.h:255
13 _event_add_read_write (xref=<optimized out>, m=0xdc29e44ee40, func=0x4020f0 <bgp_process_reads>, arg=0xdc29fc33080, fd=66, t_ptr=0xdc29fc330c0) at lib/event.c:1397
14 0x0000000000402562 in bgp_process_reads (event=<optimized out>) at bgpd/bgp_io.c:317
15 0x00000008216b7660 in event_call (event=event@entry=0x82bb21f28) at lib/event.c:2744
16 0x000000082164c686 in fpt_run (arg=0xdc29edf9e00) at lib/frr_pthread.c:386
bgpd.err has this:
Fatal error 'mutex 0x81191c73988 own 0x18c5f is on list 0x0 0x81191c69908' at line 151 in file /home/pkgbuild/worktrees/main/lib/libthr/thread/thr_mutex.c (errno = 35)
Examination of the event code shows that FRR is copying the event in event_run, this includes a hard copy of the mutex.
Then when add_unused is called it frees the mutex. FreeBSD is noticing that the mutex is the same as something that
was freed when we still have a copy of the mutex. When making a copy of the event, hard clear the mutex in
event_run. Additionally the event->yield data was being protecteed (partially) by the event->mtx. Convert
the protection over to the master->mtx as that it is protecting the event->yield values in all the other
spots. So let's just use that.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
diff --git a/lib/event.c b/lib/event.c
index 0457f9d007..1ad0f3048b 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -865,17 +865,12 @@ void event_master_set_name(struct event_loop *master, const char *name)
/* Move thread to unuse list. */
static void thread_add_unuse(struct event_loop *m, struct event *event)
{
- pthread_mutex_t mtxc = event->mtx;
-
assert(m != NULL && event != NULL);
event->hist->total_active--;
memset(event, 0, sizeof(struct event));
event->type = EVENT_UNUSED;
- /* Restore the event mutex context. */
- event->mtx = mtxc;
-
if (event_list_count(&m->unuse) < EVENT_UNUSED_DEPTH) {
event_list_add_tail(&m->unuse, event);
return;
@@ -973,7 +968,7 @@ unsigned long event_timer_remain_msec(struct event *event)
if (!event_is_scheduled(event))
return 0;
- frr_with_mutex (&event->mtx) {
+ frr_with_mutex (&event->master->mtx) {
remain = monotime_until(&event->u.sands, NULL) / 1000LL;
}
@@ -990,7 +985,7 @@ struct timeval event_timer_remain(struct event *event)
{
struct timeval remain;
- frr_with_mutex (&event->mtx) {
+ frr_with_mutex (&event->master->mtx) {
monotime_until(&event->u.sands, &remain);
}
return remain;
@@ -1031,11 +1026,8 @@ static struct event *event_get(struct event_loop *m, uint8_t type,
{
struct event *event = event_list_pop(&m->unuse);
- if (!event) {
+ if (!event)
event = XCALLOC(MTYPE_THREAD, sizeof(struct event));
- /* mutex only needs to be initialized at struct creation. */
- pthread_mutex_init(&event->mtx, NULL);
- }
event->type = type;
event->add_type = type;
@@ -1073,7 +1065,6 @@ static struct event *event_get(struct event_loop *m, uint8_t type,
static void thread_free(struct event_loop *master, struct event *event)
{
/* Free allocated resources. */
- pthread_mutex_destroy(&event->mtx);
XFREE(MTYPE_THREAD, event);
}
@@ -1394,10 +1385,8 @@ void _event_add_read_write(const struct xref_eventsched *xref,
event = event_get(m, dir, func, arg, xref);
if (event) {
- frr_with_mutex (&event->mtx) {
- event->u.fd = fd;
- thread_array[event->u.fd] = event;
- }
+ event->u.fd = fd;
+ thread_array[event->u.fd] = event;
if (t_ptr) {
*t_ptr = event;
@@ -1439,13 +1428,11 @@ static void _event_add_timer_timeval(const struct xref_eventsched *xref,
/* default lateness warning: 4s */
event->tardy_threshold = TARDY_DEFAULT_THRESHOLD;
- frr_with_mutex (&event->mtx) {
- event->u.sands = t;
- event_timer_list_add(&m->timer, event);
- if (t_ptr) {
- *t_ptr = event;
- event->ref = t_ptr;
- }
+ event->u.sands = t;
+ event_timer_list_add(&m->timer, event);
+ if (t_ptr) {
+ *t_ptr = event;
+ event->ref = t_ptr;
}
/* The timer list is sorted - if this new timer
@@ -1520,10 +1507,8 @@ void _event_add_event(const struct xref_eventsched *xref, struct event_loop *m,
break;
event = event_get(m, EVENT_EVENT, func, arg, xref);
- frr_with_mutex (&event->mtx) {
- event->u.val = val;
- event_list_add_tail(&m->event, event);
- }
+ event->u.val = val;
+ event_list_add_tail(&m->event, event);
if (t_ptr) {
*t_ptr = event;
@@ -2089,6 +2074,7 @@ static struct timeval *thread_timer_wait(struct event_timer_list_head *timers,
static struct event *event_run(struct event_loop *m, struct event *event, struct event *fetch)
{
*fetch = *event;
+
thread_add_unuse(m, event);
return fetch;
}
@@ -2624,7 +2610,7 @@ int event_should_yield(struct event *event)
{
int result;
- frr_with_mutex (&event->mtx) {
+ frr_with_mutex (&event->master->mtx) {
result = monotime_since(&event->real, NULL)
> (int64_t)event->yield;
}
@@ -2633,7 +2619,7 @@ int event_should_yield(struct event *event)
void event_set_yield_time(struct event *event, unsigned long yield_time)
{
- frr_with_mutex (&event->mtx) {
+ frr_with_mutex (&event->master->mtx) {
event->yield = yield_time;
}
}
@@ -2832,10 +2818,8 @@ void _event_execute(const struct xref_eventsched *xref, struct event_loop *m,
event = event_get(m, EVENT_EXECUTE, func, arg, xref);
/* Set its event value. */
- frr_with_mutex (&event->mtx) {
- event->u.val = val;
- event->ref = &event;
- }
+ event->u.val = val;
+ event->ref = &event;
}
/* Execute thread doing all accounting. */
diff --git a/lib/frrevent.h b/lib/frrevent.h
index 0e276249b3..86cd4a3a4c 100644
--- a/lib/frrevent.h
+++ b/lib/frrevent.h
@@ -90,7 +90,6 @@ struct event {
/* lateness warning threshold, usec. 0 if it's not a timer. */
unsigned long tardy_threshold;
const struct xref_eventsched *xref; /* origin location */
- pthread_mutex_t mtx; /* mutex for thread.c functions */
};
/* rate limit late timer warnings */