Skip to content

feat(crash-handler): opt-in sanitizer-compat feature to fix LSan ab… - #124

Merged
Jake-Shadle merged 2 commits into
EmbarkStudios:mainfrom
mlowicki-atai:fix/issue-123-sanitizer-compat-feature
Sep 25, 2026
Merged

Jake-Shadle merged 2 commits into
EmbarkStudios:mainfrom
mlowicki-atai:fix/issue-123-sanitizer-compat-feature

Conversation

@mlowicki-atai

@mlowicki-atai mlowicki-atai commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

…ort (#123)

Linking crash-handler exports an unconditional #[no_mangle] pthread_create that interposes the process's pthread_create. Under a sanitizer (-Zsanitizer=leak/address/thread) this strong symbol shadows the sanitizer's weak pthread_create alias, and the interposer's dlsym(RTLD_NEXT, ...) resolves straight to libc — bypassing the sanitizer's create-side bookkeeping while its pthread_join interceptor stays active. LSan then aborts at teardown with "Joining already joined thread".

Add an opt-in sanitizer-compat Cargo feature (off by default). When enabled, the interposer chains to the sanitizer's __interceptor_pthread_create (resolved via a link-time extern_weak reference — null when no sanitizer is linked) instead of libc, keeping the sanitizer in the loop: pthread_create -> __interceptor_pthread_create -> libc.

The feature gates BOTH the crate-level #![feature(linkage)] attribute and the weak extern block, so stable builds are entirely unaffected (feature off = no nightly requirement). A -Zsanitizer build is already nightly-only (-Zbuild-std), so turning the feature on adds no new toolchain constraint.

Implements the feature-gated approach outlined in #123.

@mlowicki-atai

Copy link
Copy Markdown
Contributor Author

@Jake-Shadle 👋 any chance you could take a look at this one?

…ort (EmbarkStudios#123)

Linking `crash-handler` exports an unconditional `#[no_mangle] pthread_create`
that interposes the process's `pthread_create`. Under a sanitizer
(`-Zsanitizer=leak`/`address`/`thread`) this strong symbol shadows the
sanitizer's weak `pthread_create` alias, and the interposer's
`dlsym(RTLD_NEXT, ...)` resolves straight to libc — bypassing the sanitizer's
create-side bookkeeping while its `pthread_join` interceptor stays active. LSan
then aborts at teardown with "Joining already joined thread".

Add an opt-in `sanitizer-compat` Cargo feature (off by default). When enabled,
the interposer chains to the sanitizer's `__interceptor_pthread_create`
(resolved via a link-time `extern_weak` reference — null when no sanitizer is
linked) instead of libc, keeping the sanitizer in the loop:
`pthread_create -> __interceptor_pthread_create -> libc`.

The feature gates BOTH the crate-level `#![feature(linkage)]` attribute and the
weak extern block, so stable builds are entirely unaffected (feature off = no
nightly requirement). A `-Zsanitizer` build is already nightly-only
(`-Zbuild-std`), so turning the feature on adds no new toolchain constraint.

Implements the feature-gated approach outlined in EmbarkStudios#123.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Jake-Shadle
Jake-Shadle force-pushed the fix/issue-123-sanitizer-compat-feature branch from faad449 to 89fae0d Compare September 25, 2026 09:00
@Jake-Shadle
Jake-Shadle merged commit b37ccc5 into EmbarkStudios:main Sep 25, 2026
15 checks passed
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.

2 participants