Skip to content

Cleanup of memory allocation and usage of events - #21943

Merged
riw777 merged 10 commits into
FRRouting:masterfrom
donaldsharp:ldpd_cleanup_of_shutdown
May 27, 2026
Merged

Cleanup of memory allocation and usage of events#21943
riw777 merged 10 commits into
FRRouting:masterfrom
donaldsharp:ldpd_cleanup_of_shutdown

Conversation

@donaldsharp

@donaldsharp donaldsharp commented May 13, 2026

Copy link
Copy Markdown
Member

Cleanup of both memory allocation and usage of events across of FRR to make the whole thing be consistent.

a) ldpd: event cleanup of unnecessary pointer setting for events, fix bug using malloc instead of calloc
b) lib: Fix null deref in frr_signal_timer
c) ospfd: Cleanup of ospf_apiserver usage of XMALLOC to XCALLOC
d) bgpd, use event_cancel instead of NULL setting in rfapi code
e) pimd, use event_cancel instead of NULL setting.
f) zebra, use event cancel instead of NULL setting.
g) Drop redundant Null setting inside of event handlers
h) Drop redundant if guards before event_cancel calling
i) Use event_is_scheduled() for truthiness of event being active or not
j) Don't need to check for NULL when using alloc functions
k) Create a test that shows bgp bmp mirroring is broken
l) Fix broken bmp mirroring.

@Jafaral

Jafaral commented May 14, 2026

Copy link
Copy Markdown
Member

@greptile review

@greptile-apps

greptile-apps Bot commented May 14, 2026

Copy link
Copy Markdown

Greptile Summary

This PR is a broad cleanup across ~120 files, standardising event-pointer truth tests to event_is_scheduled(), removing redundant manual NULL assignments in event callbacks (which the framework now handles), and upgrading bare NULL checks before event_cancel() to unconditional calls. Three commits also fix real bugs: a NULL-deref in lib/sigevent.c, a multi-queue corruption crash in bgpd/bgp_bmp.c (with a new topotest), and a timer leak in bgpd/rfapi/rfapi_import.c.

  • Mechanical sweep: ~100 files replace if (t) / t = NULL patterns with event_is_scheduled(t) and drop now-redundant manual NULL clears at callback entry, consistent with the FRR event-system contract.
  • bgpd/bgp_bmp.c: Fixes a crash where a single qitem was enqueued into every matching VRF's mirror queue; the fix allocates one qitem per VRF with a correctly scoped refcount.
  • lib/sigevent.c: Fixes a definite NULL-deref β€” the old code set sigm->t = NULL then immediately dereferenced it; the fix uses the t parameter passed to the callback instead.
  • ospfd/ospf_apiserver.c: Switches XMALLOC β†’ XCALLOC for two allocations, removing now-redundant explicit zero-inits; new->filter->origin = ANY_ORIGIN (value 2) is still set explicitly since it is non-zero.

Confidence Score: 4/5

The PR is safe to merge. All three substantive bug fixes (sigevent NULL-deref, BMP mirror multi-queue corruption, rfapi timer leak) are correct, and the new topotest covers the BMP crash scenario.

The changes are correct and the real fixes are well-motivated, but the sweep touches ~120 files across nearly every FRR daemon, which means any subtle semantic difference between t != NULL and event_is_scheduled(t) could introduce a latent issue in a path not covered by CI. The new topotest validates the most impactful fix.

The bgpd/bgp_bmp.c refcount logic in bmp_mirror_packet is the most structurally significant change and warrants a careful second read; the rest of the files are mechanical and low-risk.

Important Files Changed

Filename Overview
lib/sigevent.c Fixes a NULL-deref crash: old code set sigm->t = NULL then used sigm->t->master; fix correctly uses the callback's own event parameter t->master.
bgpd/bgp_bmp.c Fixes crash where a single qitem was enqueued into multiple VRF mirror queues; now allocates a fresh qitem per-VRF with correctly scoped refcount. Also removes redundant t_read = NULL and adds event_is_scheduled checks.
bgpd/rfapi/rfapi_import.c Replaces bare timer = NULL assignments before event_add_timer with event_cancel(), properly cancelling any running timer before re-arming instead of leaking it.
ospfd/ospf_apiserver.c Switches to XCALLOC (zero-init) removing redundant field NULLing; retains explicit origin = ANY_ORIGIN (value 2) since it is non-zero. Removes unreachable NULL check after stream_new.
lib/nexthop.c Removes unreachable NULL-check branch after XREALLOC; FRR's allocator aborts on OOM so the fallback path (clamping new_stack->num_labels) was dead code.
pimd/pim_pim.c Replaces bare t = NULL with event_cancel() in pim_sock_add, ensuring any existing read event is properly cancelled when the socket is recreated.
tests/lib/test_memory.c Removes dead NULL check after XREALLOC; FRR's XREALLOC never returns NULL (aborts on OOM), so the conditional copy was unreachable.
bgpd/bgp_fsm.c Mechanical: replaces all bare event-pointer NULL tests with event_is_scheduled() calls across GR, LLGR, routeadv, maxmed, and delayopen timer checks.
tests/topotests/bgp_bmp/test_bgp_bmp_mirror.py New topotest that reproduces the multi-target BMP mirror crash with two bmp targets sharing a single BGP instance; validates queue integrity and session health.
lib/zclient.c Drops redundant t_write = NULL and t_read = NULL at callback entry; removes spurious extra NULL in BUFFER_PENDING case; uses event_is_scheduled for t_connect guard in zclient_start.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["bmp_mirror_packet(peer, ...)"] --> B["For each bgp_vrf in bm->bgp"]
    B --> C{"bmpbgp = bmp_bgp_find(bgp_vrf)\nfound?"}
    C -- No --> B
    C -- Yes --> D["qitem = NULL  (per-VRF local)"]
    D --> E["For each bmp_targets bt with mirror=true"]
    E --> F{"bgp_vrf matches\npeer->bgp?"}
    F -- No --> E
    F -- Yes --> G["For each bmp session"]
    G --> H{"qitem == NULL?"}
    H -- Yes --> I["XCALLOC new qitem\nset peerid/tv/len/data"]
    I --> J["refcount++\nmirrorpos = qitem\npullwr_bump"]
    H -- No --> J
    J --> G
    G -- done --> K{"qitem != NULL?"}
    K -- No --> B
    K -- Yes --> L["Add to bmpbgp->mirrorq\nbmp_mirror_cull\nupdate qsizemax"]
    L --> B
    B -- done --> M["return 0"]
Loading

Reviews (1): Last reviewed commit: "bgpd: Fix crash in bgp_bmp.c with a mirr..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@donaldsharp
donaldsharp force-pushed the ldpd_cleanup_of_shutdown branch from 9fbf40f to c177973 Compare May 15, 2026 14:50
@riw777
riw777 self-requested a review May 19, 2026 20:55

@riw777 riw777 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

@donaldsharp
donaldsharp force-pushed the ldpd_cleanup_of_shutdown branch 2 times, most recently from 5a17289 to c50d3ad Compare May 20, 2026 14:24
@donaldsharp
donaldsharp force-pushed the ldpd_cleanup_of_shutdown branch from c50d3ad to 22c2d4a Compare May 22, 2026 14:18
There are several classes of problems:

a) event pointer is set to NULL inside the handler function.
This is unnecessary and redundant, so we can safely remove the
set.

b) event_cancel is called then the event pointer is set to
NULL.  Again this is redundant.

c) fresh calloc call we set the event pointer to NULL.
This is redundant.

d) Actual bug, use malloc to grab memory and then
call some event_add_XX function.  The malloc'ed
memory may not be null the initial event_add_XX
function will safely return since it believes
that the thread pointer is already there.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
ospf_apiserver.c is using XMALLOC for alloc'ing memory,
switch over to XCALLOC and drop the NULL pointer assignments
to event structures as well as the memset.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
We have this pattern:

event = NULL
event_add_timer(..., &event...);

FRR code should never set a event to NULL as that any existing
timer will be run but the ability to stop it has been lost,
modify the code to cancel the event and then add the timer again.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
The code was using this as a pattern:

event = NULL;
event_add_timer(...,&event,...);

This can leave a dangling event in the event system.  Explicitly
cancel and then restart.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
Instead of null'ing pointers, explicitly cancel the event timer
as that leaving a event dangling is dangerous and causes problems.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
The event system when calling a event handler has already
set the event pointer to NULL that was handed in.  There
is no need to do this again.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
The pattern of:

if (event)
   event_cancel();

makes no sense, just do a `event_cancel()`.  That is sufficient.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
The pattern:

if (event)

Should really be:

if (event_is_scheduled(event))

Replace.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
XCALLOC/XMALLOC and XREALLOC cannot fail, as such
checking for NULL is redundant and unnecessary, remove.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
The md_alg variable is being set 2 times, no need.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
@donaldsharp
donaldsharp force-pushed the ldpd_cleanup_of_shutdown branch from 22c2d4a to 1a1ea77 Compare May 26, 2026 18:38
@frrbot frrbot Bot added the bfd label May 26, 2026
@riw777
riw777 merged commit d457a68 into FRRouting:master May 27, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants