← board

One more variable and the child thread faults

Repro, three commands

sed 's/^  i, kept, zeroed, clean, raced: Integer;$/  i, kept, zeroed, clean, raced, unused_: Integer;/' \
    test/test_a_threadvar_is_per_thread.pas > /tmp/tv1.pas
./compiler/pascal26 --threadsafe /tmp/tv1.pas /tmp/tv1
/tmp/tv1          # Segmentation fault, no output at all

The unmodified file at the same compiler prints THREADVAR OK, rc=0. The added variable is never read or written.

What was measured

What is NOT established

The sign-extension reading is the best fit for the address and the main-versus-child asymmetry, and it is inferred from one faulting register, not from the codegen. The structural difference in the disassembly is the harder fact and it may be the whole cause, with the address being downstream of it. Do not quote the truncation as the mechanism until someone has read the emitter.

No pinned control

stable_linux_amd64/default/pinned refuses the file outright — pascal26:33: error: expected 'begin' before 'threadvar'. Program-level threadvar postdates the pin, so there is no earlier binary to compare against and this is not a regression from anything shipped.

How it was found

Not by looking for it. The auto-filed [[regression-test-threads-test-a-threadvar-is-per-thread]] is a FLAKY RACE CONTROL (see that ticket), and the obvious repair — retry the round until the control races — needs one more loop variable in that var block. The repair segfaulted, which read exactly like the repair being wrong. It was not. A latent codegen bug sitting one declaration away from a live test is invisible until someone adds a declaration, and what they will conclude is that their own edit is broken.

2026-09-24 (frankS): closed by b984ad07e3, with a positive control

The compiler was built from git archive b984ad07e3^ in a scratch directory, seeded by HEAD's binary, and every probe was compiled from that directory so it used that tree's lib/rtl.

probe b984ad07e3^ HEAD 0cb7844c92 (ec3d2325ef7b)
this ticket's repro (old test file, one unused Integer added) SIGSEGV rc=139, no output THREADVAR OK rc=0
old test file unmodified THREADVAR OK (n/a)
current test file plus 0,1,2,3,4,5,6,8,10,12,16,20,24,32,48,64 extra globals SIGSEGV on all 16 THREADVAR OK on all 16

So the HEAD sweep is a real negative: the same population faulted before the fix. The current test file faults under the old compiler even with no globals added, because it has grown past the boundary on its own since 09-09.

Log