poc: add heartbeat functionality to native backend#1742
Conversation
Instructions and example for changelogPlease add an entry to Example: ## Unreleased
### Features
- add heartbeat functionality to native backend ([#1742](https://github.com/getsentry/sentry-native/pull/1742))If none of the above apply, you can opt out of this check by adding |
| if (env_path) { | ||
| sentry_envelope_t *envelope = sentry__envelope_from_path(env_path); | ||
| if (envelope && options && options->transport) { |
There was a problem hiding this comment.
Bug: In capture_and_send_app_hang, an envelope allocated by sentry__envelope_from_path is leaked if options->transport is NULL, as the freeing logic is skipped.
Severity: MEDIUM
Suggested Fix
Ensure the envelope is always freed, regardless of whether sentry__capture_envelope is called. This can be achieved by moving the sentry_envelope_free call to a location that executes in all paths, or by adding an else block to handle the case where the transport is unavailable and free the envelope there.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/backends/native/sentry_crash_daemon.c#L2748-L2750
Potential issue: In the `capture_and_send_app_hang` function, an envelope is allocated
from a file path using `sentry__envelope_from_path`. This envelope is intended to be
freed within `sentry__capture_envelope`. However, the call to `sentry__capture_envelope`
is conditional on `options->transport` being non-NULL. If transport initialization fails
and `options->transport` is `NULL`, the condition is false, the function is not called,
and the allocated envelope is never freed, resulting in a memory leak. Since the daemon
is a long-running process, this leak can accumulate over time.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1f2c69d. Configure here.
| if (timer) { | ||
| wait_handles[1] = timer; | ||
| wait_count = 2; | ||
| } |
There was a problem hiding this comment.
Timer failure disables hangs
Medium Severity
If the Windows app-hang timer fails to initialize, the daemon won't set up its polling mechanism. This prevents app-hang detection from running, even when the feature is enabled and the host continues to send heartbeats.
Reviewed by Cursor Bugbot for commit 1f2c69d. Configure here.
| /* Always advance last_fired_hb, even if capture failed — | ||
| * prevents a retry storm against a wedged thread. The next | ||
| * heartbeat advance re-arms detection naturally. */ | ||
| last_fired_hb = hb; |
There was a problem hiding this comment.
Failed capture still cools down
Medium Severity
After SENTRY_APP_HANG_FIRE, the daemon always sets last_fired_hb to the current heartbeat even when capture_and_send_app_hang fails (for example OpenThread with a zero or invalid app_hang_target_tid). While the monitored thread stays frozen the heartbeat timestamp does not change, so later ticks hit the cooldown branch and no ApplicationNotResponding event is sent.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 1f2c69d. Configure here.
|
|
||
| /* Relaxed 64-bit store. On x64 this is a single mov. On x86 the value | ||
| * may tear, but that is OK — see the comment in sentry_crash_context.h. */ | ||
| ctx->app_hang_last_heartbeat_ms = sentry__app_hang_now_ms(); |
There was a problem hiding this comment.
Heartbeat use after free
Medium Severity
sentry_app_hang_heartbeat copies g_app_hang_shmem into a local pointer, then writes shared heartbeat fields through it. During native_backend_shutdown, another thread can clear that global and unmap IPC between the load and the store, so a concurrent heartbeat can touch freed shared memory.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 1f2c69d. Configure here.
| } | ||
| sentry__path_remove(env_path); | ||
| sentry__path_free(env_path); | ||
| } |
There was a problem hiding this comment.
App hang upload not flushed
High Severity
After an app-hang envelope is queued via sentry__capture_envelope, the daemon keeps running and never flushes its HTTP transport. Normal sentry_close() then terminates the daemon with TerminateProcess, so background sends can be cut off and the ApplicationNotResponding event may never reach Sentry.
Reviewed by Cursor Bugbot for commit 1f2c69d. Configure here.


Resolves https://github.com/getsentry/team-gdx/issues/155
Warning
WIP 🚧🔨⏳⛔