Skip to content

Fix segfault in pipe ele:floor for girder elements#2050

Closed
ChristopherMayes wants to merge 3 commits into
mainfrom
fix_issue_2049_tao_pipe_girder_crash
Closed

Fix segfault in pipe ele:floor for girder elements#2050
ChristopherMayes wants to merge 3 commits into
mainfrom
fix_issue_2049_tao_pipe_girder_crash

Conversation

@ChristopherMayes

@ChristopherMayes ChristopherMayes commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #2049.

Problem

Running Tao with a lattice containing a girder element and querying the floor coordinates of that girder crashed with a segmentation fault:

tao -lat lat.bmad -noplot -command "pipe ele:floor g1 beginning"

Minimal reproducer:

beginning[beta_a] = 1
beginning[beta_b] = 1
beginning[e_tot] = 100e6
parameter[geometry] = open

p1: pipe, L = 1
p2: pipe, L = 2
g1: girder = {p1, p2}

lat: line = (p1, p2)
use, lat
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

The same crash also occurred for the more common case where a girder's slaves are multipass_lord elements (e.g. a cryomodule girder over a multipass linac line).

Cause

In write_this_ele_floor (tao/code/tao_pipe_cmd.f90), the code special-cased super_lord$ and girder_lord$ to skip the slave recursion, then unconditionally called:

ele0 => pointer_to_next_ele(ele, -1)

pointer_to_next_ele returns null() for any lord that is not a super_lord, so ele0%floor on the next line dereferenced a null pointer for every girder.

A naive fix that descends one level with pointer_to_slave(girder, 1) is not enough either: when the girder's slaves are themselves multipass_lord elements, the result still lives outside the tracking part of the lattice and pointer_to_next_ele still returns null.

Fix

Added a dedicated girder_lord branch in write_this_ele_floor that uses find_element_ends, which already walks through nested lord chains (multipass_lord, super_lord, nested girders) down to actual tracking elements:

  • beginning → upstream floor of the first tracking slave (from ele1 returned by find_element_ends)
  • center → the girder's own ele%floor (midpoint of the slave span)
  • end → downstream floor of the last tracking slave (ele2)

If find_element_ends cannot resolve the ends (e.g. an ill-defined girder), the routine emits an invalid message instead of dereferencing null.

Verification

Before the fix, both the minimal reproducer above and a real linac model with a multipass cryomodule girder (L1_CM1) segfaulted on pipe ele:floor <girder> beginning. After the fix, both return sensible floor coordinates:

Tao: pipe ele:floor g1 beginning
Reference;REAL_ARR;F;  0.00...E+00;  0.00...E+00;  0.00...E+00; ...

Tao: pipe ele:floor g1 center
Reference;REAL_ARR;F;  0.00...E+00;  0.00...E+00;  1.50...E+00; ...

Tao: pipe ele:floor g1 end
Reference;REAL_ARR;F;  0.00...E+00;  0.00...E+00;  3.00...E+00; ...

Tests

Added regression_tests/pytao/girder_floor/ with two minimal lattices and a pytest-based regression test (test_girder_floor.py):

  • lat.bmad — simple girder over two pipes
  • lat_multipass.bmad — girder whose slaves are multipass_lord elements

Test cases:

  • test_girder_floor_beginning_does_not_crash — confirms pipe ele:floor g1 beginning no longer crashes the subprocess
  • test_girder_floor_beginning_matches_first_slave — confirms beginning matches the upstream floor of the first slave
  • test_girder_floor_end_matches_last_slave — confirms end matches the downstream floor of the last slave
  • test_girder_floor_center — confirms center matches the midpoint of the slave span
  • test_girder_floor_multipass_does_not_crash — confirms the girder-over-multipass case (the original real-world crash) returns sensible coordinates without crashing

All five cases pass against the patched build.

Files changed

  • tao/code/tao_pipe_cmd.f90 — replaced the broken pointer_to_next_ele path with a girder_lord branch backed by find_element_ends.
  • regression_tests/pytao/girder_floor/lat.bmad — minimal girder lattice.
  • regression_tests/pytao/girder_floor/lat_multipass.bmad — girder over multipass lattice.
  • regression_tests/pytao/girder_floor/test_girder_floor.py — pytest regression tests (5 cases).

Acknowledgement

This PR was prepared with assistance from GitHub Copilot (Claude Opus 4.7, Anthropic) running in the VS Code agent surface. The model performed the codebase exploration, diagnosis, edits, build, and test authoring; all changes were reviewed and verified locally.

@ChristopherMayes ChristopherMayes changed the title Fix https://github.com/bmad-sim/bmad-ecosystem/issues/2049 Fix #2049 Jun 8, 2026
@ChristopherMayes ChristopherMayes marked this pull request as ready for review June 8, 2026 21:19
@ChristopherMayes ChristopherMayes changed the title Fix #2049 Fix segfault in pipe ele:floor for girder elements Jun 8, 2026
@DavidSagan

Copy link
Copy Markdown
Member

@ChristopherMayes I put in a fix (PR #2052). The fix includes a regression test but this is different from the tests here. If you want to include your tests ,please open a new PR.

@DavidSagan DavidSagan closed this Jun 11, 2026
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.

Tao crashes on "pipe ele:floor g1 beginning" with a girder g1

2 participants