ankidroid / Anki-Android

AnkiDroid: Anki flashcards on Android. Your secret trick to achieve superhuman information retention.
GNU General Public License v3.0
8.41k stars 2.19k forks source link

[Bug] `OnRenderProcessGone` is not handled by Anki Desktop WebViews #15695

Open david-allison opened 6 months ago

david-allison commented 6 months ago

[FATAL:crashpad_client_linux.cc(745)] Render process (6903)'s crash wasn't handled by all associated webviews, triggering application crash.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 6824 >>> com.ichi2.anki <<<

backtrace:
  #00  pc 0x00000000026f2c44  /data/app/~~nIabJGklkL2XhnxMyPPoTA==/com.google.android.trichromelibrary_616717830--WVNBIaQFGowESE3DVAbLw==/base.apk!libmonochrome.so (BuildId: db06232df52ca789848a2727c27680f63b243c65)
  #01  pc 0x00000000035cdf61  /data/app/~~nIabJGklkL2XhnxMyPPoTA==/com.google.android.trichromelibrary_616717830--WVNBIaQFGowESE3DVAbLw==/base.apk!libmonochrome.so (BuildId: db06232df52ca789848a2727c27680f63b243c65)
  #02  pc 0x0000000000c5b44f  /data/app/~~nIabJGklkL2XhnxMyPPoTA==/com.google.android.trichromelibrary_616717830--WVNBIaQFGowESE3DVAbLw==/base.apk!libmonochrome.so (BuildId: db06232df52ca789848a2727c27680f63b243c65)
  #03  pc 0x0000000002636ea3  /data/app/~~nIabJGklkL2XhnxMyPPoTA==/com.google.android.trichromelibrary_616717830--WVNBIaQFGowESE3DVAbLw==/base.apk!libmonochrome.so (BuildId: db06232df52ca789848a2727c27680f63b243c65)
  #04  pc 0x00000000026345d3  /data/app/~~nIabJGklkL2XhnxMyPPoTA==/com.google.android.trichromelibrary_616717830--WVNBIaQFGowESE3DVAbLw==/base.apk!libmonochrome.so (BuildId: db06232df52ca789848a2727c27680f63b243c65)
  #05  pc 0x0000000001b2ba91  /data/app/~~nIabJGklkL2XhnxMyPPoTA==/com.google.android.trichromelibrary_616717830--WVNBIaQFGowESE3DVAbLw==/base.apk!libmonochrome.so (BuildId: db06232df52ca789848a2727c27680f63b243c65)
  #06  pc 0x0000000002ec9925  /data/app/~~nIabJGklkL2XhnxMyPPoTA==/com.google.android.trichromelibrary_616717830--WVNBIaQFGowESE3DVAbLw==/base.apk!libmonochrome.so (BuildId: db06232df52ca789848a2727c27680f63b243c65)
  #07  pc 0x0000000002ec98f7  /data/app/~~nIabJGklkL2XhnxMyPPoTA==/com.google.android.trichromelibrary_616717830--WVNBIaQFGowESE3DVAbLw==/base.apk!libmonochrome.so (BuildId: db06232df52ca789848a2727c27680f63b243c65)
  #08  pc 0x00000000000102e5  /system/lib/libutils.so (android::Looper::pollInner(int)+700)
  #09  pc 0x000000000000ffcf  /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+62)
  #10  pc 0x00000000000e6f53  /system/lib/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long long, int)+24)
  #11  pc 0x0000000000422a17  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (art_jni_trampoline+78)
  #12  pc 0x0000000000d709bb  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (android.os.MessageQueue.next+266)
  #13  pc 0x0000000000d6ccbb  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (android.os.Looper.loopOnce+74)
  #14  pc 0x0000000000d6cb63  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (android.os.Looper.loop+1034)
  #15  pc 0x0000000000a9ad8b  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (android.app.ActivityThread.main+1282)
  #16  pc 0x00000000003bd1d5  /apex/com.android.art/lib/libart.so (art_quick_invoke_stub_internal+68)
  #17  pc 0x00000000002cc731  /apex/com.android.art/lib/libart.so (void art::quick_invoke_reg_setup<true>(art::ArtMethod*, unsigned int*, unsigned int, art::Thread*, art::JValue*, char const*) (.__uniq.192663596067446536341070919852553954320.llvm.16200230356545185596)+260)
  #18  pc 0x000000000028a4f3  /apex/com.android.art/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+182)
  #19  pc 0x0000000000313969  /apex/com.android.art/lib/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*) (.__uniq.245181933781456475607640333933569312899.llvm.2586733929373010981)+40)
  #20  pc 0x0000000000351425  /apex/com.android.art/lib/libart.so (_jobject* art::InvokeMethod<(art::PointerSize)4>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned int)+372)
  #21  pc 0x00000000004d8e5d  /apex/com.android.art/lib/libart.so (art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*) (.__uniq.165753521025965369065708152063621506277)+40)
  #22  pc 0x0000000000410db1  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (art_jni_trampoline+56)
  #23  pc 0x0000000001106117  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run+118)
  #24  pc 0x0000000001111417  /data/misc/apexdata/com.android.art/dalvik-cache/arm/boot.oat (com.android.internal.os.ZygoteInit.main+2638)
  #25  pc 0x00000000003bd1d5  /apex/com.android.art/lib/libart.so (art_quick_invoke_stub_internal+68)
  #26  pc 0x00000000002cc731  /apex/com.android.art/lib/libart.so (void art::quick_invoke_reg_setup<true>(art::ArtMethod*, unsigned int*, unsigned int, art::Thread*, art::JValue*, char const*) (.__uniq.192663596067446536341070919852553954320.llvm.16200230356545185596)+260)
  #27  pc 0x000000000028a4f3  /apex/com.android.art/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+182)
  #28  pc 0x0000000000313969  /apex/com.android.art/lib/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*) (.__uniq.245181933781456475607640333933569312899.llvm.2586733929373010981)+40)
  #29  pc 0x000000000038818d  /apex/com.android.art/lib/libart.so (art::JValue art::InvokeWithVarArgs<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, std::__va_list)+176)
  #30  pc 0x00000000002b7e4b  /apex/com.android.art/lib/libart.so (art::JValue art::InvokeWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+42)
  #31  pc 0x00000000004a5f1b  /apex/com.android.art/lib/libart.so (art::JNI<true>::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+74)
  #32  pc 0x000000000007882d  /system/lib/libandroid_runtime.so (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+28)
  #33  pc 0x0000000000081cc1  /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool)+608)
  #34  pc 0x000000000000253f  /system/bin/app_process32 (main+978)
  #35  pc 0x000000000005e5c5  /apex/com.android.runtime/lib/bionic/libc.so (__libc_init+56)
mikehardy commented 6 months ago

Original work for OnRenderProcessGone:

mikehardy commented 6 months ago

It appears from repo search that we create WebViewClients in a handful of places, but the PageWebViewClient is the one that all the pages exposed from desktop extend from

https://github.com/ankidroid/Anki-Android/blob/main/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageWebViewClient.kt

Assumption: Much of the OnRenderProcessGone logic is reusable (and as a criteria for a fix here: should be reused) from the original work

@david-allison - now that we are in Kotlin and have extension functions, does it seem like a better path to do a deeper inheritance hierarchy and have e.g. a "RenderProcessGoneHandlingWebView" parent that AbstractFlashcardViewer and PageViewClient both use, or to use Kotlin extension functions (somehow, unclear due to my inexperience) to slice the OnRenderProcessGone handling in?

david-allison commented 6 months ago

Probably inheritance so it's harder to forget, no strong opinion

mikehardy commented 6 months ago

Okay - I prefer that myself, I find the extensions to be a little "aspect-oriented-programming-like" where things slice in sometimes in non-obvious ways from non-location-coherent spots and for me that is non-obvious. Inheritance is obvious to the point it cannot be ignored.

So, implementation path here is to make a new superclass for the WebView objects we create, I propose RednerProcessGoneHandlingWebView which is a long name but also totally obvious as to what it is for

Then inside that object implement OnRenderProcessGone using extraction as much as possible from the current WebView class inside AbstractFlashcardViewer

Then use that new super-class for AbstractFlashcardViewer and PageWebViewClient, and hopefully we handle this problem well (not doing anything in the background, doing a reload once in foreground as an attempt to workaround, going back to deckpicker (I think that's what happens?) with a toast (I think that's what happens?) if multiple crashes happen

Out of time for the day so marking this as "needs help" but hopefully the analysis is useful to anyone that has time, or to a future version of me that may have time

github-actions[bot] commented 1 month ago

Hello 👋, this issue has been opened for more than 3 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically