mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-09-14 00:35:08 +00:00
Ignore platform finalizer-watchdog crashes in crash reports
BinderInternal$GcWatcher.finalize() TimeoutExceptions are a known AOSP issue raised by the finalizer watchdog on the FinalizerDaemon thread. They contain no app frames and cannot be caught or prevented by app code, so the report only nags users with an unactionable "send crash report?" prompt. Extend the existing OOM junk filter in UnexpectedCrashSaver to drop TimeoutExceptions whose message or stack matches the finalizer watchdog path. App-thrown TimeoutExceptions and all other crashes are still reported.
This commit is contained in:
+20
-2
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package com.greenart7c3.nostrsigner.service.crashreports
|
||||
|
||||
import java.util.concurrent.TimeoutException
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -33,12 +34,29 @@ class UnexpectedCrashSaver(
|
||||
t: Thread,
|
||||
e: Throwable,
|
||||
) {
|
||||
if (e !is OutOfMemoryError) {
|
||||
// OOM reports are junk
|
||||
if (!isJunkReport(e)) {
|
||||
scope.launch {
|
||||
cache.writeReport(ReportAssembler().buildReport(e))
|
||||
}
|
||||
}
|
||||
defaultUEH!!.uncaughtException(t, e)
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Crashes we never prompt the user to report because nobody can act on them:
|
||||
* - OutOfMemoryError: junk reports.
|
||||
* - Platform finalizer-watchdog timeouts (e.g.
|
||||
* `BinderInternal$GcWatcher.finalize() timed out after 10 seconds`): a known
|
||||
* AOSP issue raised on the FinalizerDaemon thread with no app frames. The OS
|
||||
* kills the process regardless; app code cannot catch, prevent, or fix it.
|
||||
*/
|
||||
fun isJunkReport(e: Throwable): Boolean = e is OutOfMemoryError || isPlatformFinalizerTimeout(e)
|
||||
|
||||
private fun isPlatformFinalizerTimeout(e: Throwable): Boolean = e is TimeoutException &&
|
||||
(
|
||||
e.message?.contains("finalize() timed out") == true ||
|
||||
e.stackTrace.any { it.className.startsWith("java.lang.Daemons\$FinalizerDaemon") }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.greenart7c3.nostrsigner.service.crashreports
|
||||
|
||||
import java.util.concurrent.TimeoutException
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class UnexpectedCrashSaverTest {
|
||||
private fun finalizerWatchdogCrash(): TimeoutException {
|
||||
val e = TimeoutException("com.android.internal.os.BinderInternal\$GcWatcher.finalize() timed out after 10 seconds")
|
||||
e.stackTrace =
|
||||
arrayOf(
|
||||
StackTraceElement("com.android.internal.os.BinderInternal\$GcWatcher", "finalize", "BinderInternal.java", 64),
|
||||
StackTraceElement("java.lang.Daemons\$FinalizerDaemon", "doFinalize", "Daemons.java", 389),
|
||||
StackTraceElement("java.lang.Daemons\$FinalizerDaemon", "processReference", "Daemons.java", 369),
|
||||
StackTraceElement("java.lang.Daemons\$FinalizerDaemon", "runInternal", "Daemons.java", 354),
|
||||
StackTraceElement("java.lang.Daemons\$Daemon", "run", "Daemons.java", 135),
|
||||
StackTraceElement("java.lang.Thread", "run", "Thread.java", 1564),
|
||||
)
|
||||
return e
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `binder gc watcher finalizer timeout is junk`() {
|
||||
assertTrue(UnexpectedCrashSaver.isJunkReport(finalizerWatchdogCrash()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `finalizer daemon stack is junk even without the message`() {
|
||||
val e = TimeoutException(null as String?)
|
||||
e.stackTrace =
|
||||
arrayOf(
|
||||
StackTraceElement("android.os.BinderProxy", "finalize", "BinderProxy.java", 100),
|
||||
StackTraceElement("java.lang.Daemons\$FinalizerDaemon", "doFinalize", "Daemons.java", 389),
|
||||
)
|
||||
assertTrue(UnexpectedCrashSaver.isJunkReport(e))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `out of memory is junk`() {
|
||||
assertTrue(UnexpectedCrashSaver.isJunkReport(OutOfMemoryError()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `app timeout exception is not junk`() {
|
||||
assertFalse(UnexpectedCrashSaver.isJunkReport(TimeoutException("socket timed out")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `regular crash is not junk`() {
|
||||
assertFalse(UnexpectedCrashSaver.isJunkReport(IllegalStateException("boom")))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user