Skip to content
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Fixes

- Fix main thread identification for tombstone (native crash) events ([#5742](https://github.com/getsentry/sentry-java/pull/5742))

### Dependencies

- Bump Native SDK from v0.15.2 to v0.15.3 ([#5728](https://github.com/getsentry/sentry-java/pull/5728))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ private List<SentryThread> createThreads(
// the backend currently requires a stack-trace in exception
exc.setStacktrace(stacktrace);
}

// thread id always equals the process id,
// so we use it to reliably detect the main thread
if (tombstone.pid == threadEntryValue.id) {
// the OS may provide a (truncated) process name; normalize it
// back to "main" so downstream consumers see a consistent name
thread.setName("main");
thread.setMain(true);
}
threads.add(thread);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ class TombstoneIntegrationTest : ApplicationExitIntegrationTestBase<TombstoneHin
val crashedThreadId = 21891L
assertEquals(crashedThreadId, event.exceptions!![0].threadId)
val crashedThread = event.threads!!.find { thread -> thread.id == crashedThreadId }
assertEquals("samples.android", crashedThread!!.name)
assertEquals("main", crashedThread!!.name)
assertTrue(crashedThread.isMain!!)
assertTrue(crashedThread.isCrashed!!)

// Verify that frames from the app's native library are marked as in-app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import java.io.StringWriter
import java.util.zip.GZIPInputStream
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertNotNull
import org.mockito.kotlin.mock

Expand Down Expand Up @@ -99,6 +100,10 @@ class TombstoneParserTest {

// threads
assertEquals(62, event.threads!!.size)
val mainThread = event.threads!!.single { it.isMain == true }
assertEquals(21891, mainThread.id)
assertEquals("main", mainThread.name)

for (thread in event.threads!!) {
assertNotNull(thread.id)
if (thread.id == crashedThreadId) {
Expand Down Expand Up @@ -397,6 +402,73 @@ class TombstoneParserTest {
assertEquals(expectedJson, actualJson)
}

@Test
fun `identifies the main thread via pid matching the thread id and normalizes its name`() {
val tombstone =
Tombstone.Builder()
.pid(1000)
.tid(2000)
.signal(Signal(11, "SIGSEGV", 1, "SEGV_MAPERR", false, 0, 0, false, 0, null))
// main thread: id == pid, but the OS renamed it to the process name
.addThread(
TombstoneThread(
1000,
"io.sentry.samples.android",
emptyList(),
emptyList(),
emptyList(),
listOf(BacktraceFrame(0, 0x100, 0, "main", 0, "/system/lib64/libc.so", 0, "")),
emptyList(),
0,
0,
)
)
.addThread(
TombstoneThread(
2000,
"crashed-worker",
emptyList(),
emptyList(),
emptyList(),
listOf(BacktraceFrame(0, 0x200, 0, "crash", 0, "/system/lib64/libc.so", 0, "")),
emptyList(),
0,
0,
)
)
.addThread(
TombstoneThread(
3000,
"Thread-3",
emptyList(),
emptyList(),
emptyList(),
listOf(BacktraceFrame(0, 0x300, 0, "work", 0, "/system/lib64/libc.so", 0, "")),
emptyList(),
0,
0,
)
)
.build()

val event = parser.parse(tombstone)
val threads = event.threads!!

val main = threads.single { it.isMain == true }
assertEquals(1000, main.id)
assertEquals("main", main.name)

val crashed = threads.single { it.isCrashed == true }
assertEquals(2000, crashed.id)
assertNotEquals(true, crashed.isMain)
assertEquals("crashed-worker", crashed.name)

val background = threads.single { it.id == 3000L }
assertNotEquals(true, background.isMain)
assertNotEquals(true, background.isCrashed)
assertEquals("Thread-3", background.name)
}

@Test
fun `parses tombstone when nativeLibraryDir is null`() {
val tombstoneStream =
Expand Down
Loading