Skip to content

Fix the segfault on Ctrl-C; print slot drops only at shutdown - #20

Merged
aferaudo merged 2 commits into
feat/prb-blockfrom
fix/shutdown-segfault
Nov 11, 2026
Merged

aferaudo merged 2 commits into
feat/prb-blockfrom
fix/shutdown-segfault

Conversation

@aferaudo

Copy link
Copy Markdown
Collaborator

Summary

  • No more segfault on Ctrl-C (Ctrl-C crashes the controller (segfault at shutdown) #19). libe3 deletes the SMs in agent.stop(), and main() still used two of them afterwards. Now the slot pipeline stops first, the drop summary is taken, and only then does the agent stop. The prb_block codelet is unloaded through main's own relay, which outlives the SM.
  • No more [E3SMLayer1] dropped N slot(s) in the last second. With slot_filter.ue_free_only, every UL slot a UE transmits in is a ue_busy drop, so this line was printed every second while a UE was attached. The counters stay: the shutdown summary prints them by reason, and logging.drops_log_path still writes the CSV.
  • Based on Apply a dApp's PRB block in the gNB's scheduler #17, where the crash comes from. Once Apply a dApp's PRB block in the gNB's scheduler #17 is merged, retarget this PR to main.

Tested (x86, Ubuntu 22.04, GCC 11.4, Release, on e61d7fd):

  • Controller alone, Ctrl-C after 5 s, with prb_block.enabled true and false: before, exit 139 (SIGSEGV) both times; after, exit 0 with the drop summary and Stopped..
  • Each commit builds on its own; test_l1_kpm_sm and test_spectrum_sm pass.
  • Not run yet: with a gNB and a dApp attached.

Type of change

  • Bug fix
  • New feature / enhancement
  • New Service Model
  • Refactor (no behavior change)
  • Documentation
  • Test / CI / packaging
  • Other (explain):

Linked issue

Closes #19

Twin-repo coordination

  • This PR does not change the E3 wire protocol or public ABI, OR a paired PR exists in each affected twin repo (link below).

Paired PR(s): none.

🤖 Generated with Claude Code

libe3 0.2.5 deletes every SM inside agent.stop() (SmRegistry::clear()),
but main() still used two of them afterwards:

- spectrum_ptr->stop(), to unload the prb_block codelet: a call into a
  deleted object, so every Ctrl-C ended in a segfault (exit 139), with or
  without prb_block.enabled;
- layer1_ptr->drops_summary(), for the shutdown summary: a read of freed
  memory.

Stop the slot pipeline first, since its worker is the only thread that
bumps the L1-KPM counters, take the summary, then stop the agent. The
prb_block codelet is unloaded through main's own relay, which outlives
the SM; the Spectrum SM has normally done it already, inside
agent.stop().

Fixes #19.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
With slot_filter.ue_free_only, every UL slot a UE transmits in is a
ue_busy drop, so "[E3SMLayer1] dropped N slot(s) in the last second" was
printed every second for as long as a UE was attached. Those drops are
by design, and every fault already prints its own message (geometry
mismatch, a helper that wrote nothing, a short blob, an encode or a send
failure).

The counters stay: the shutdown summary prints them by reason, and
logging.drops_log_path still writes one CSV row per second.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
@aferaudo
aferaudo merged commit f043b78 into feat/prb-block Nov 11, 2026
2 checks passed
aferaudo added a commit that referenced this pull request Nov 11, 2026
With prb_block.enabled (off by default), a dApp's Spectrum SM PRB
blacklist control (RAN function 1, control 1) reaches ocudu's scheduler,
which keeps every PDSCH and PUSCH allocation off those PRBs, in every
slot, DL and UL, until the next control replaces the list. PUCCH, PDCCH,
SSB, PRACH, SRS and CSI-RS keep their PRBs.

- The first RAN function 1 subscription loads the new prb_block codelet
  on ocudu's sched_prb_block hook, instead of the eCPRI IQ pipeline; the
  last one unloads it, which clears the block. PrbBlockRelay hands the
  newest block to the gNB from the main loop and ACKs it then; the
  codelet reports the first scheduler slot that applies it. A PRB outside
  the carrier, a full queue or no codelet is a NACK.
- New shared header codelets/include/jbpf_e3_prb_block_api.h,
  byte-identical with ocudu's copy.
- Spectrum SM: the current e3sm_spectrum.asn grammar, plus the legacy
  Spectrum-IQDataIndication section, whose bytes do not change; the SM
  types are generated with libe3's codec set.
- Closed-loop stage records, and tools/latrec_closed_loop.py, which joins
  the controller's and the dApp's rings.
- The controller stops without the SMs libe3 already deleted, and prints
  slot drops only in the shutdown summary (#20).

Fixes #19.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
@aferaudo
aferaudo deleted the fix/shutdown-segfault branch November 11, 2026 23:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant