-
-
Notifications
You must be signed in to change notification settings - Fork 214
feat: in proc App Hang capture #1806
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
a5b7c54
in-proc app hang capture
bitsandfoxes ddc9e01
fixed comment
bitsandfoxes 10191dc
Merge branch 'master' into feat/app-hang-inproc
bitsandfoxes c46fc68
updated changelog
bitsandfoxes 493af79
updated the app hang example
bitsandfoxes 92b7ec6
.
bitsandfoxes 4fe992e
style
bitsandfoxes f8fa212
fixed linux race conditions
bitsandfoxes a187a1f
.
bitsandfoxes 375d4b1
Merge branch 'master' into feat/app-hang-inproc
bitsandfoxes 2c784da
style
bitsandfoxes 58bb34d
Merge branch 'feat/app-hang-inproc' of https://github.com/getsentry/s…
bitsandfoxes 25c47ca
renamed better
bitsandfoxes cab5bda
.
bitsandfoxes 73488e5
bot review
bitsandfoxes 2ee1805
resolved restart deadlock
bitsandfoxes 9b9f26a
release active flag
bitsandfoxes 77779b9
docs
bitsandfoxes a10b76b
free handle
bitsandfoxes e2b6254
Merge branch 'master' into feat/app-hang-inproc
bitsandfoxes 3cd1df5
POD
bitsandfoxes 6e0cf58
public api comment
bitsandfoxes 3b8267a
used sentry monotonic clock
bitsandfoxes 88e1e73
updated changelog
bitsandfoxes 386f4f7
restore errno
bitsandfoxes c07e41c
Merge branch 'master' into feat/app-hang-inproc
bitsandfoxes File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| // In-process app-hang detection, shared state and helpers. The latch, heartbeat | ||
| // API, and capture predicate are the app-thread hot path: app threads write the | ||
| // latch via the heartbeat (timestamped with sentry__monotonic_time), the | ||
| // watchdog worker in sentry_app_hang_monitor.c reads it. | ||
| #include "sentry_app_hang_latch.h" | ||
| #include "sentry_sync.h" | ||
| #include "sentry_utils.h" | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| #if defined(SENTRY_PLATFORM_WINDOWS) | ||
| # include <windows.h> | ||
| #elif defined(SENTRY_PLATFORM_LINUX) || defined(SENTRY_PLATFORM_ANDROID) | ||
| # include <sys/syscall.h> | ||
| # include <unistd.h> | ||
| #else // SENTRY_PLATFORM_MACOS and other POSIX | ||
| # include <pthread.h> | ||
| #endif | ||
|
|
||
| bool | ||
| sentry__app_hang_should_capture( | ||
| uint64_t hb, uint64_t now, uint64_t timeout_ms, uint64_t last_fired_hb) | ||
| { | ||
| if (hb == 0 || timeout_ms == 0) { | ||
| return false; | ||
| } | ||
| if (now < hb || (now - hb) < timeout_ms) { | ||
| return false; | ||
| } | ||
| if (hb == last_fired_hb) { | ||
| return false; // already fired for this freeze | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| // The latch is touched by app threads (writers, via the heartbeat) and the | ||
| // single watchdog worker (reader). An explicit mutex would put a lock on the | ||
| // heartbeat hot path, not ideal. | ||
| // The two fields are accessed with 64-bit atomics: | ||
| // | ||
| // - last_heartbeat_ms: written on every heartbeat, read by the worker. | ||
| // Needs 64-bit-atomic access so a 32-bit platform can't observe a torn | ||
| // half-updated timestamp. | ||
| // - target_tid: write-once (0 -> first heartbeating tid). The worker only | ||
| // uses it as a stackwalker argument so a relaxed read is sufficient. | ||
| // | ||
| // Both fields use the sentry__atomic_*_u64 helpers, which provide full 64-bit | ||
| // atomic (tear-free) access on every platform. Where the target has native | ||
| // 64-bit atomics (AArch64, x86-64, ...) this is lock-free; on ARMv7 the | ||
| // compiler lowers it to a libatomic call backed by a lock pool. That is fine | ||
| // here: the access is off any signal handler (both writer and worker run in | ||
| // normal thread context) and the heartbeat cadence dwarfs the few-ns lock, so | ||
| // the lock only delivers the tear-free guarantee we already need. | ||
| static uint64_t g_target_tid = 0; | ||
| static uint64_t g_last_heartbeat_ms = 0; | ||
| static volatile long g_app_hang_active = 0; | ||
|
|
||
| void | ||
| sentry__app_hang_set_active(bool active) | ||
| { | ||
| sentry__atomic_store(&g_app_hang_active, active ? 1 : 0); | ||
| } | ||
|
|
||
| uint64_t | ||
| sentry__app_hang_current_tid(void) | ||
| { | ||
| #if defined(SENTRY_PLATFORM_LINUX) || defined(SENTRY_PLATFORM_ANDROID) | ||
| return (uint64_t)syscall(SYS_gettid); | ||
| #elif defined(SENTRY_PLATFORM_MACOS) | ||
| uint64_t tid = 0; | ||
| pthread_threadid_np(pthread_self(), &tid); | ||
| return tid; | ||
| #elif defined(SENTRY_PLATFORM_WINDOWS) | ||
| return (uint64_t)GetCurrentThreadId(); | ||
| #else | ||
| return 0; | ||
| #endif | ||
| } | ||
|
|
||
| sentry_app_hang_latch_t | ||
| sentry__app_hang_current_latch(void) | ||
| { | ||
| sentry_app_hang_latch_t latch; | ||
| latch.target_tid = sentry__atomic_fetch_u64(&g_target_tid); | ||
| latch.last_heartbeat_ms = sentry__atomic_fetch_u64(&g_last_heartbeat_ms); | ||
| return latch; | ||
| } | ||
|
|
||
| void | ||
| sentry__app_hang_latch_reset(void) | ||
| { | ||
| sentry__atomic_store_u64(&g_target_tid, 0); | ||
| sentry__atomic_store_u64(&g_last_heartbeat_ms, 0); | ||
| } | ||
|
|
||
| void | ||
| sentry_app_hang_heartbeat(void) | ||
| { | ||
| if (!sentry__atomic_fetch(&g_app_hang_active)) { | ||
| return; | ||
| } | ||
| uint64_t tid = sentry__app_hang_current_tid(); | ||
|
|
||
| uint64_t target = sentry__atomic_fetch_u64(&g_target_tid); | ||
| if (target == 0) { | ||
| // Latch the first heartbeating thread. | ||
| sentry__atomic_store_u64(&g_target_tid, tid); | ||
| target = tid; | ||
| } | ||
|
bitsandfoxes marked this conversation as resolved.
|
||
| if (target == tid) { | ||
| // ignore heartbeats from other threads | ||
| sentry__atomic_store_u64( | ||
| &g_last_heartbeat_ms, sentry__monotonic_time()); | ||
| } | ||
|
sentry[bot] marked this conversation as resolved.
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #ifndef SENTRY_APP_HANG_LATCH_H_INCLUDED | ||
| #define SENTRY_APP_HANG_LATCH_H_INCLUDED | ||
|
|
||
| #include "sentry_boot.h" | ||
| #include "sentry_value.h" | ||
|
|
||
| #define SENTRY_APP_HANG_MAX_FRAMES 128 | ||
|
|
||
| bool sentry__app_hang_should_capture( | ||
| uint64_t hb, uint64_t now, uint64_t timeout_ms, uint64_t last_fired_hb); | ||
|
|
||
| typedef struct { | ||
| uint64_t target_tid; | ||
| uint64_t last_heartbeat_ms; | ||
| } sentry_app_hang_latch_t; | ||
|
|
||
| uint64_t sentry__app_hang_current_tid(void); | ||
| sentry_app_hang_latch_t sentry__app_hang_current_latch(void); | ||
| void sentry__app_hang_latch_reset(void); | ||
|
|
||
| // Enables/disables the heartbeat fast-path. The watchdog monitor sets this on | ||
| // start and clears it on stop, so sentry_app_hang_heartbeat() is a cheap no-op | ||
| // when detection is not running. | ||
| void sentry__app_hang_set_active(bool active); | ||
|
|
||
| sentry_value_t sentry__app_hang_make_event( | ||
| void **ips, size_t frame_count, uint64_t freeze_ms); | ||
|
|
||
| #endif |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.