Skip to content

πŸ› fix(tsan): initialise libxml2 at load time via C constructor#34

Merged
MFranceschi6 merged 2 commits into
mainfrom
claude/epic-28-xmlnode-linenumber
Apr 6, 2026
Merged

πŸ› fix(tsan): initialise libxml2 at load time via C constructor#34
MFranceschi6 merged 2 commits into
mainfrom
claude/epic-28-xmlnode-linenumber

Conversation

@MFranceschi6
Copy link
Copy Markdown
Owner

Summary

  • Adds a C __attribute__((constructor)) in SwiftXMLCoderCShim.c that calls xmlInitParser() and pre-warms the UTF-8 encoding handler at library-load time, in a single-threaded context
  • Removes the swiftxmlcoder_warm_encoding_handler call from LibXML2.initializeOnce (now handled by the constructor)
  • Fixes the TSan SEGV in test_encodeDecode_concurrent_roundTrip reported on PR ⬆️ chore: bump actions/github-script from 7 to 8Β #31

Root cause

Under TSan, its pthread interceptors interfere with libxml2's internal pthread_once guard inside xmlInitParser(). This leaves the encoding-handler table NULL when xmlGetCharEncodingHandler is subsequently called β€” causing a SEGV in the very warm-up that was meant to prevent that crash. Moving initialisation to a C constructor ensures it runs before TSan instruments any pthread primitive.

Test plan

  • CI TSan lane (Concurrency (TSan, ubuntu-22.04)) passes
  • All other lanes remain green

πŸ€– Generated with Claude Code

MFranceschi6 and others added 2 commits April 5, 2026 22:07
Add `XMLNode.lineNumber: Int?` backed by `xmlGetLineNo()` from libxml2.
Returns the 1-based source line number recorded during parsing, or `nil`
when unavailable (programmatically created nodes or libxml2 returns 0).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Under ThreadSanitizer, TSan's pthread interceptors interfere with
libxml2's internal pthread_once guard inside xmlInitParser(), leaving
the encoding-handler table NULL when xmlGetCharEncodingHandler is called
from a concurrent thread β€” causing a SEGV in the warm-up that was meant
to prevent that very crash.

Add an __attribute__((constructor)) in SwiftXMLCoderCShim.c that runs
xmlInitParser() and the UTF-8 handler warm-up at library-load time, in a
single-threaded context, before TSan instruments any pthread primitives.
This guarantees libxml2's global tables are fully populated before any
thread is created.

LibXML2.initializeOnce now only calls xmlInitParser() as a no-op
safeguard for static-linking configurations that do not run constructors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@MFranceschi6 MFranceschi6 merged commit 1509fff into main Apr 6, 2026
15 checks passed
@MFranceschi6 MFranceschi6 deleted the claude/epic-28-xmlnode-linenumber branch April 6, 2026 14:09
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