Symptom
The javascript engine built with OpenMP and run -j8 on darwin-arm64 exits ~3/10 with
Segmentation violation signal in rule: <a different rule each run>
(observed in rules from three different files across three failures). The varying location means a shared data structure is being corrupted, not a rule defect. Exit code 1; Soufflé's own signal handler reports the rule, so no crash dump is produced.
Conditions
- Only under concurrent memory-pressure load (two large clang compiles running beside it). 10/10 clean on a quiet machine, 10/10 clean under pure CPU-spin load, 6/6 clean under a debugger, one TSAN run clean (both perturb timing; stock libomp is not TSAN-instrumented).
- Only observed on darwin-arm64 (weak memory). The same engine binary pattern on linux-x64 and Windows x64 (TSO) ran clean in all rounds.
- Serial runs: no failures anywhere, outputs byte-identical across platforms.
Why javascript specifically
Among the five engines, only the javascript program creates new symbols during the solve (substr/cat chains in its module-resolution rules). The other four mostly probe symbols that already exist in the facts. That makes concurrent symbol-table insertion (ConcurrentInsertOnlyHashMap / the symbol table's publication path) the prime suspect: the seqlock/publication-fence overlay applied for the earlier arm64 crashes fences the BTree only.
Repro
On an arm64 Mac, stage a large javascript subject's facts, build the -par flavor (AXIOM_SOLVE_PARALLEL=1 run-souffle.sh --language javascript --prepare), then run the engine -j 8 in a loop while two clang++ -O1 -fsyntax-only compiles of a ~9MB generated C++ file loop beside it. Expect a failure within ~10 runs.
Impact
Parallel default was flipped to opt-in (serial default everywhere) until this is fenced; measured opt-in value on quiet arm64 hardware is 1.5–3x on top of the current rules, so the fix is worth having.
Symptom
The javascript engine built with OpenMP and run
-j8on darwin-arm64 exits ~3/10 with(observed in rules from three different files across three failures). The varying location means a shared data structure is being corrupted, not a rule defect. Exit code 1; Soufflé's own signal handler reports the rule, so no crash dump is produced.
Conditions
Why javascript specifically
Among the five engines, only the javascript program creates new symbols during the solve (
substr/catchains in its module-resolution rules). The other four mostly probe symbols that already exist in the facts. That makes concurrent symbol-table insertion (ConcurrentInsertOnlyHashMap/ the symbol table's publication path) the prime suspect: the seqlock/publication-fence overlay applied for the earlier arm64 crashes fences the BTree only.Repro
On an arm64 Mac, stage a large javascript subject's facts, build the
-parflavor (AXIOM_SOLVE_PARALLEL=1 run-souffle.sh --language javascript --prepare), then run the engine-j 8in a loop while twoclang++ -O1 -fsyntax-onlycompiles of a ~9MB generated C++ file loop beside it. Expect a failure within ~10 runs.Impact
Parallel default was flipped to opt-in (serial default everywhere) until this is fenced; measured opt-in value on quiet arm64 hardware is 1.5–3x on top of the current rules, so the fix is worth having.