Repository navigation
Triage main-branch validation failures and glibc 2.44 startup crash #2814
Description
Purpose and maintainer decision
While addressing the Swift review in #2436, I reproduced several independent failures in implementations already present on main. The candidate changes are preserved in #2809, but I am opening this issue for a maintainer decision before pursuing that PR further.
Please decide which findings should be fixed, whether the allocator change should use a focused backport or a dependency update, and how accepted work should be split into focused issues/PRs. This report is a triage inventory, not a request to merge all of #2809 as one change. None of these proposals is a prerequisite imposed on the Swift review or its maintainer-run census.
Version and environment
- Baseline: main
8530c8cd1c1ac8e1e3d2962bc213a8c9025fea0a. - Candidate: fix: isolate validation and handle empty initialization state #2809 at
678bc5841d67bd44a9b65101e4167b018169a1c3. - Linux x86_64, glibc 2.44, GCC 16; built from source, standard binary.
- After the allocator fix, the binary reports
codebase-memory-mcp dev. Before it, even--versionexited with SIGSEGV beforemain. - Local sanitizer runs used ASan/UBSan and
UBSAN_OPTIONS=halt_on_error=1. - Lint comparison used CI's cppcheck 2.20.0 and clang-format 20. Local cppcheck 2.22 produced additional diagnostics on unchanged code; these were not treated as proof of a regression in fix(swift): preserve declaration identity and compatible call edges #2436.
The affected pre-fix CLI, MCP, runner, Perl, ObjectScript, venue-contract and allocator implementations were compared with the main baseline. The signature-buffer guard described below already exists in #2436; #2809 carries the same safeguard for main.
1. C runner HOME isolation does not cover inherited XDG paths
Actual: tests/test_main.c redirects HOME but leaves XDG_CONFIG_HOME, XDG_DATA_HOME, and XDG_CACHE_HOME inherited. CLI fixtures can therefore resolve configuration outside their private HOME. In the observed run, CLI tests reached the developer's real Zed configuration path and 22 CLI tests failed.
Expected: fixture-owned client configuration stays within the fixture's private boundary regardless of inherited XDG settings.
Reproduction: run the CLI suite with those three XDG variables set, rather than unset. For safe reproduction, point them at disposable directories outside the runner's fixture HOME, not an account's real configuration:
scripts/test.sh --suites cli BUILD_DIR=build/c-reproCheck the resolved configuration paths as well as assertions. This is an isolation boundary issue, not just a test expectation mismatch.
Candidate: add the three XDG variables to the runner's existing client-home override handling and extend tests/test_smoke_fixture_contract.sh. Shell fixtures already handle their configuration boundary separately.
2. Git mnemonic prefixes break detect_changes hunk seeds
Actual: the hunk command in src/mcp/mcp.c inherits diff.mnemonicPrefix=true, while its parser expects +++ b/. Precise changed-symbol seeds become whole-file seeds. MCP assertions then fail; assertion exits also produced LeakSanitizer reports, which were secondary symptoms in this reproduction.
Expected: test-impact results do not depend on the contributor's global Git prefix preferences.
After building the runner on the baseline:
GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0=diff.mnemonicPrefix \
GIT_CONFIG_VALUE_0=true \
UBSAN_OPTIONS=halt_on_error=1 \
build/c-repro/test-runner mcpThe existing detect_changes_seed_list_reports_hunk_without_walk case is one relevant regression. The pre-fix focused reproduction failed with mnemonic prefixes enabled.
As a control, the unchanged Swift-branch binary produced 749 passing CLI/MCP tests and 5 platform skips after clearing inherited XDG overrides and global Git configuration.
Candidate: reuse the existing CBM_TEST_IMPACT_GIT_PINS and CBM_TEST_IMPACT_DIFF_FLAGS for both platform hunk commands, and enable mnemonic prefixes in the existing MCP walk fixture.
3. Empty-input library calls trigger UBSan
Strict sanitizer runs found null arguments on empty-input paths:
| Location | Empty-input operation | Candidate behavior |
|---|---|---|
internal/cbm/doclink_perl.c |
Empty package/subdeclaration sorts | Skip the empty sorts |
src/pipeline/doc_links_perl.c |
Empty declaration sort | Skip the empty sort |
| Both ObjectScript external scanners | memcpy(payload, NULL, 0) during deserialize |
Copy only when length is nonzero |
internal/cbm/callable_sig.c |
Initial buffer-growth copy with no previous bytes | Copy only when the previous length is nonzero |
src/pipeline/doc_links_rst.c |
Search of an empty configuration table | Return no configuration before calling bsearch |
Representative reproduction:
UBSAN_OPTIONS=halt_on_error=1 scripts/test.sh \
--suites extraction,pipeline,callable_sig,grammar_probe_g \
BUILD_DIR=build/c-reproThe baseline first stopped in the signature-buffer path and the RST/grammar coverage exposed the empty configuration lookup. The ObjectScript and Perl diagnostics were also observed before the guards. Expected behavior is to retain valid empty results without sanitizer diagnostics.
The existing Perl documentation regression was extended with a POD-only module: its module documentation remains present and it has no Function definitions. It still has its valid Module definition.
4. Venue help probes invoke Bash before selecting Python
Actual: tests/test_venue_parity_contract.sh invokes every entry with Bash before its *.py dispatch. On a desktop with ImageMagick installed, a Python import statement can execute ImageMagick's import program and wait for graphical input.
Reproduction: run bash tests/test_venue_parity_contract.sh on such a host and inspect the help-probe child processes. The observed blocked child was ImageMagick, not the Python harness.
Expected/candidate: dispatch Python entries directly to Python, and Bash entries to Bash. The corrected existing contract completed without an intervention.
5. Production binary crashes before main on glibc 2.44
Actual: the vendored mimalloc 3.3.2 page map can still be NULL when libc calls free(NULL) before allocator constructors. The observed stack was mi_free -> newlocale -> libstdc++ locale/ios initialization -> loader; --version exited 139. Debugging confirmed the NULL page-map lookup.
This matches upstream microsoft/mimalloc#1341, with the focused fix in b2226c195fe884223f6d6f68ea52df476e57e5c2.
Independent reproduction: the ELF pre-initialization probe in #2809 calls mi_free(NULL) from .preinit_array, then checks ordinary allocation/free in main. Copying this probe into the baseline's tests directory and running it reproduced exit 139 before the patch and exit 0 afterward, independently of waiting for libc to trigger the early call.
Candidate: backport the small upstream empty-page-map initialization for both layouts, including the allocation-failure path. This preserves the hot free path and does not disable the allocator or upgrade the whole dependency. Also track included mimalloc source/header dependencies for the test and TSan objects, matching the existing production dependency pattern. The probe is Linux/ELF-specific; other platforms explicitly report it as not applicable.
Decision requested: focused backport versus an upstream dependency update, and whether the build-dependency/probe work should accompany it.
Validation of the candidate, with limits
- Affected extraction, MCP, pipeline, CLI and known-class suites: 1,690 passed, 5 platform skips, no sanitizer diagnostics.
- Final canonical
scripts/test.sh BUILD_DIR=build/c-review-completewith strict UBSan reached All tests passed, including all enabled production guards. - That entry's unit phase reported 9,802 passed, 0 failed, 10 platform skips. A transient TLS fixture-clone error skipped incremental setup without counting its tests. A separate run of the same final test binary passed all 164 incremental tests, exit 0 and no sanitizer diagnostics. Total verified with that binary: 9,966 tests; this is not a claim that all 9,966 ran in one uninterrupted entry.
- Production startup, parent/worker watchdogs, TLS budget, worker error transport, watcher switches, request/session scope, security-string allow-list and destructive-ordering guards passed.
- CI-mode lint with the pinned tools, diff-scoped clang-tidy, and
git diff --checkpassed. - The three changed vendored sources have updated checksums; the integrity gate passed for 1,083 files.
- Default full clang-tidy still has existing baseline findings. This report does not propose lowering thresholds or adding suppressions. Related historical discussion: Local pre-commit hook (scripts/hooks/pre-commit -> make lint) blocks every commit: ~5,100 pre-existing clang-tidy findings across 113 files #1264.
- These full local results are for fix: isolate validation and handle empty initialization state #2809, not the Swift head in fix(swift): preserve declaration identity and compatible call edges #2436. Cross-platform CI is separate evidence and is not inferred from local Linux results.
Relationship to existing work
I searched existing issues for mimalloc, mnemonicPrefix, and XDG before opening this report. #1696 tracks shell smoke/soak/profiling runtime isolation; item 1 here concerns the C runner's client configuration paths. #589 concerns source build diagnostics and #2606 concerns Windows allocator behavior, rather than the demonstrated pre-main glibc crash.
Please indicate which items you want pursued and the desired split. I will keep #2809 as a draft reference while that decision is pending, rather than treating this inventory as approval to land the combined patch.
Activity