Skip to content
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

Identify the error reporting thread in native crashes #2087

Merged
merged 1 commit into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## TBD

### Enhancements

* Native crashes will now identify the crashing/error reporting thread
[#2087](https://github.com/bugsnag/bugsnag-android/pull/2087)

## 6.8.0 (2024-09-30)

### Enhancements
Expand Down
1 change: 1 addition & 0 deletions bugsnag-plugin-android-ndk/src/main/jni/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ typedef struct {

typedef struct {
pid_t id;
bool is_reporting_thread;
char name[16];
char state[13];
} bsg_thread;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <pthread.h>
#include <stdexcept>
#include <string>
#include <unistd.h>

#include "../utils/crash_info.h"
#include "../utils/serializer.h"
Expand Down Expand Up @@ -58,7 +59,7 @@ void bsg_handle_cpp_terminate() {

if (bsg_global_env->send_threads != SEND_THREADS_NEVER) {
bsg_global_env->next_event.thread_count = bsg_capture_thread_states(
bsg_global_env->next_event.threads, BUGSNAG_THREADS_MAX);
gettid(), bsg_global_env->next_event.threads, BUGSNAG_THREADS_MAX);
} else {
bsg_global_env->next_event.thread_count = 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ void bsg_handle_signal(int signum, siginfo_t *info,

if (bsg_global_env->send_threads != SEND_THREADS_NEVER) {
bsg_global_env->next_event.thread_count = bsg_capture_thread_states(
bsg_global_env->next_event.threads, BUGSNAG_THREADS_MAX);
gettid(), bsg_global_env->next_event.threads, BUGSNAG_THREADS_MAX);
} else {
bsg_global_env->next_event.thread_count = 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,12 @@ static bool bsg_write_threads(BSG_KSJSONEncodeContext *json,
CHECKED(bsg_ksjsonbeginObject(json, NULL));
{
CHECKED(JSON_LIMITED_STRING_ELEMENT("id", id_string));

if (thread->is_reporting_thread) {
CHECKED(
bsg_ksjsonaddBooleanElement(json, "errorReportingThread", true));
}

CHECKED(JSON_LIMITED_STRING_ELEMENT("name", thread->name));
CHECKED(JSON_LIMITED_STRING_ELEMENT("state", thread->state));
CHECKED(JSON_CONSTANT_ELEMENT("type", "c"));
Expand Down
5 changes: 4 additions & 1 deletion bugsnag-plugin-android-ndk/src/main/jni/utils/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ static bool read_thread_state(bsg_thread *dest, const char *tid) {
return parse_success;
}

size_t bsg_capture_thread_states(bsg_thread *threads, size_t max_threads) {
size_t bsg_capture_thread_states(pid_t reporting_tid, bsg_thread *threads,
size_t max_threads) {
size_t total_thread_count = 0;
struct dirent64 *entry;
char buffer[1024];
Expand All @@ -187,6 +188,8 @@ size_t bsg_capture_thread_states(bsg_thread *threads, size_t max_threads) {
for (offset = 0; offset < available && total_thread_count < max_threads;) {
entry = (struct dirent64 *)(buffer + offset);
if (read_thread_state(&threads[total_thread_count], entry->d_name)) {
threads[total_thread_count].is_reporting_thread =
threads[total_thread_count].id == reporting_tid;
total_thread_count += 1;
}

Expand Down
2 changes: 1 addition & 1 deletion bugsnag-plugin-android-ndk/src/main/jni/utils/threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ extern "C" {

#define MAX_STAT_PATH_LENGTH 64

size_t bsg_capture_thread_states(bsg_thread *threads,
size_t bsg_capture_thread_states(pid_t reporting_tid, bsg_thread *threads,
size_t max_threads) __asyncsafe;

#ifdef __cplusplus
Expand Down
6 changes: 6 additions & 0 deletions features/smoke_tests/04_unhandled.feature
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,9 @@ Feature: Unhandled smoke tests
# Breadcrumbs
And the event has a "manual" breadcrumb named "CXXExceptionSmokeScenario"

# Threads validation
And the error payload field "events.0.threads" is a non-empty array
And the event "threads.0.id" matches "^[0-9]+$"
And the event "threads.0.name" is not null
And the event "threads.0.type" equals "c"
And the thread with name "roid.mazerunner" contains the error reporting flag
Loading