Title: Fix thread safety, walkVM anchor recovery, and musl compatibility by jbachorik · Pull Request #400 · DataDog/java-profiler · GitHub
Open Graph Title: Fix thread safety, walkVM anchor recovery, and musl compatibility by jbachorik · Pull Request #400 · DataDog/java-profiler
X Title: Fix thread safety, walkVM anchor recovery, and musl compatibility by jbachorik · Pull Request #400 · DataDog/java-profiler
Description: What does this PR do?: Fixes crashes and assertion failures caused by VMThread accessor calls on non-JavaThread types and partially-initialized threads. Adds walkVM anchor recovery for interpreter frames on musl (where DWARF CFI is absent in __syscall_cp_asm). Enables CSTACK_VM as the default stack walking mode on Linux with proper safety guards. Commits: Scan all native libs for thread entry points — replaces fragile findJvmLibrary/findLibraryByName with a full scan, fixing thread entry detection on glibc, musl, and Rust binaries Guard JavaThread-specific VMThread accessors for non-JavaThread safety — guards anchor(), inDeopt(), compiledMethod() with cachedIsJavaThread(); adds isThreadAccessible() check in walkVM/checkFault for partially-mapped threads (GraalVM 25 aarch64); fixes torn write in cacheJavaThread() Fix test infrastructure for cross-platform stability — CStackInjector fallback for J9; TagContextTest pins cstack=default Suppress debug asserts in at()/cast_to() under crash protection — avoids assertion failures when crash-protected code dereferences suspect pointers Restore error frames for truncated stacks in walkVM — break_no_anchor for JavaThreads when symbol resolution fails; break_no_symbol for non-Java threads where JavaFrameAnchor is inapplicable Fix pthread_key_t sentinel for musl — key value 0 is valid on musl (glibc reserves it); uses volatile bool flag instead. Removes stale TLS priming declarations Add walkVM anchor recovery for interpreter frames on musl — when DWARF unwinding can't reach Java frames (musl's __syscall_cp_asm lacks .cfi directives), reads interpreter frames directly from VMJavaFrameAnchor's FP. Uses x86_64 HotSpot convention (lastJavaFP != 0 → interpreter frame) with getMethodId()+validatedId() safety. Includes inline recovery mid-loop, post-loop fallback, and getFrame() redirect. All anchor paths validate sp bounds and depth limits before re-entering the unwind loop Report aborted tests as SKIPPED in ProfilerTestRunner — JUnit ABORTED status was conflated with FAILED, causing false test failures on musl Motivation: While porting native memory allocation profiler support from async-profiler, running walkVM on more native threads exposed crashes from unchecked anchor()/inDeopt()/compiledMethod() calls on non-JavaThread types. On musl-amd64, CSTACK_VM (now the default on Linux) produced zero Java frames because DWARF unwinding couldn't bridge the gap through __syscall_cp_asm (which lacks CFI directives) to reach the Java frame area. Additional Notes: The CSTACK_VM default gives richer mixed Java+native stack traces. Previously this caused crashes because anchor(), inDeopt(), and compiledMethod() assumed they were always called on JavaThread instances. The cachedIsJavaThread() guard caches the vtable check in ProfiledThread for O(1) subsequent lookups. On musl-amd64, the walkVM anchor recovery works as follows: DWARF unwinding processes native frames until it hits __syscall_cp_asm (no FDE) FrameDesc::default_frame advances SP via fp + 16, which doesn't bridge the gap When method_name == NULL (unresolvable frame) and anchor is available, the inline recovery reads the interpreter frame directly from anchor->lastJavaFP() using InterpreterFrame::method_offset If the inline path doesn't fire, the post-loop fallback tries the same approach after DWARF exhaustion Both paths validate sp bounds (sp < bottom, alignment) before goto unwind_loop How to test the change?: ./gradlew :ddprof-lib:buildDebug ./utils/run-docker-tests.sh --mount --libc=glibc --arch=aarch64 --jdk=25 \ --tests="*BoundMethodHandleMetadataSizeTest*" ./utils/run-docker-tests.sh --mount --libc=musl --arch=x64 --jdk=17 \ --tests="*TagContextTest*" ./utils/run-docker-tests.sh --mount --libc=glibc --tests="*NativeThreadTest*" ./utils/run-docker-tests.sh --mount --libc=musl --tests=".*NativeThreadTest.*" For Datadog employees: If this PR touches code that signs or publishes builds or packages, or handles credentials of any kind, I've requested a review from @DataDog/security-design-and-guidance. This PR doesn't touch any of that. JIRA: [JIRA-XXXX] 🤖 Generated with Claude Code
Open Graph Description: What does this PR do?: Fixes crashes and assertion failures caused by VMThread accessor calls on non-JavaThread types and partially-initialized threads. Adds walkVM anchor recovery for interpreter ...
X Description: What does this PR do?: Fixes crashes and assertion failures caused by VMThread accessor calls on non-JavaThread types and partially-initialized threads. Adds walkVM anchor recovery for interpreter ...
Opengraph URL: https://github.com/DataDog/java-profiler/pull/400
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/commits/:range(.:format) |
| route-controller | pull_requests |
| route-action | commits |
| fetch-nonce | v2:0ac5ac9f-a9e2-e7d0-908b-dc626e385405 |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | 8776:C4024:4BF664D:65CC859:6A655A6A |
| html-safe-nonce | 7b4970de0afde6015044b3abdb1bd8725944752d602d80600cdda0e80665af59 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4Nzc2OkM0MDI0OjRCRjY2NEQ6NjVDQzg1OTo2QTY1NUE2QSIsInZpc2l0b3JfaWQiOiI3MzM1NzQ4OTE4NjYzNTM1MjEwIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 6832371d44d7cce94436cf7aa96254555812cdf4d37282729c522c22ee4003a5 |
| hovercard-subject-tag | pull_request:3331663290 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/DataDog/java-profiler/pull/400/commits/a79bafa48aee426a1676917ab6d701126880b869 |
| twitter:image | https://avatars.githubusercontent.com/u/738413?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/738413?s=400&v=4 |
| og:image:alt | What does this PR do?: Fixes crashes and assertion failures caused by VMThread accessor calls on non-JavaThread types and partially-initialized threads. Adds walkVM anchor recovery for interpreter ... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 52c76df668885aaff23b50bdca1fa1ea44ac9c1553e888ebc70ff1e4daa4625b |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/DataDog/java-profiler git https://github.com/DataDog/java-profiler.git |
| octolytics-dimension-user_id | 365230 |
| octolytics-dimension-user_login | DataDog |
| octolytics-dimension-repository_id | 585532470 |
| octolytics-dimension-repository_nwo | DataDog/java-profiler |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 585532470 |
| octolytics-dimension-repository_network_root_nwo | DataDog/java-profiler |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 309153364422b3c499922d1a2a6404910a58ed8e |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width