firebase / firebase-unity-sdk

The Firebase SDK for Unity
http://firebase.google.com
Apache License 2.0
195 stars 31 forks source link

[Bug] SIGSEGV - Pure virtual function called! #1006

Open shanemccartney opened 2 weeks ago

shanemccartney commented 2 weeks ago

Description

We have caught the following issue with Firebase 11.9.0

In the Thread message in Google Play there is the message "Pure virtual function called!"

Reproducing the issue

This does not seem to affect all users so far it seems to affect lower end Android devices like the Lenovo TB310FU with Android 13 (SDK 33)

Firebase Unity SDK Version

11.9.0

Unity editor version

2021.3.33f1

Installation Method

.unitypackage

Problematic Firebase Component(s)

Database

Other Firebase Component(s) in use

Analytics, Authentication, Crashlytics, DynamicLinks, Remote Config, Storage

Additional SDKs you are using

No response

Targeted Platform(s)

Android

Unity editor platform

Mac

Scripting Runtime

IL2CPP

Release Distribution Type

Pre-built SDK from https://firebase.google.com/download/unity

Relevant Log Output

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 1881 >>> com.theapp <<<

backtrace:
  #00  pc 0x0000000000053324  /apex/com.android.runtime/lib64/bionic/libc.so (abort+180)
  #01  pc 0x000000000033b1cc  /data/app/~~Xzi9mZ4hZj3vG7OLKnwmew==/com.theapp-fth9NRBb3RJsQYuigNJB5A==/lib/arm64/libFirebaseCppApp-11_9_0.so (abort_message+236)
  #02  pc 0x0000000000337f3c  /data/app/~~Xzi9mZ4hZj3vG7OLKnwmew==/com.theapp-fth9NRBb3RJsQYuigNJB5A==/lib/arm64/libFirebaseCppApp-11_9_0.so (__cxa_pure_virtual+16)
  #03  pc 0x00000000002e6d7c  /data/app/~~Xzi9mZ4hZj3vG7OLKnwmew==/com.theapp-fth9NRBb3RJsQYuigNJB5A==/lib/arm64/libFirebaseCppApp-11_9_0.so (firebase::storage::internal::ControllerInternal::CppStorageListenerCallback(_JNIEnv*, _jclass*, long, long, _jobject*, unsigned char)+328)
  #04  pc 0x0000000000351e30  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+144)
  #05  pc 0x00000000005b980c  /apex/com.android.art/lib64/libart.so (nterp_helper+3852)
  #06  pc 0x00000000000009fe  /data/user/0/com.theapp/cache/storage_resources_lib.jar (com.google.firebase.storage.internal.cpp.CppStorageListener.onProgress+46)
  #07  pc 0x00000000005ba674  /apex/com.android.art/lib64/libart.so (nterp_helper+7540)
  #08  pc 0x00000000002da364  /data/app/~~Xzi9mZ4hZj3vG7OLKnwmew==/com.theapp-fth9NRBb3RJsQYuigNJB5A==/oat/arm64/base.vdex (com.google.firebase.storage.j.a+8)
  #09  pc 0x00000000005ba674  /apex/com.android.art/lib64/libart.so (nterp_helper+7540)
  #10  pc 0x00000000002dcd28  /data/app/~~Xzi9mZ4hZj3vG7OLKnwmew==/com.theapp-fth9NRBb3RJsQYuigNJB5A==/oat/arm64/base.vdex (com.google.firebase.storage.TaskListenerImpl.g+4)
  #11  pc 0x00000000005b9854  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #12  pc 0x00000000002dcba8  /data/app/~~Xzi9mZ4hZj3vG7OLKnwmew==/com.theapp-fth9NRBb3RJsQYuigNJB5A==/oat/arm64/base.vdex (com.google.firebase.storage.TaskListenerImpl.b)
  #13  pc 0x00000000005b8934  /apex/com.android.art/lib64/libart.so (nterp_helper+52)
  #14  pc 0x00000000002dcaf0  /data/app/~~Xzi9mZ4hZj3vG7OLKnwmew==/com.theapp-fth9NRBb3RJsQYuigNJB5A==/oat/arm64/base.vdex (com.google.firebase.storage.x.run+12)
  #15  pc 0x0000000000ab5e1c  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.os.Handler.dispatchMessage+76)
  #16  pc 0x0000000000ab9ac8  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.os.Looper.loopOnce+1000)
  #17  pc 0x0000000000ab962c  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.os.Looper.loop+1132)
  #18  pc 0x0000000000864ec4  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.app.ActivityThread.main+2404)
  #19  pc 0x000000000033b680  /apex/com.android.art/lib64/libart.so (art_quick_invoke_static_stub+640)
  #20  pc 0x000000000037cb18  /apex/com.android.art/lib64/libart.so (_jobject* art::InvokeMethod<(art::PointerSize)8>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned long)+1556)
  #21  pc 0x000000000037c4f4  /apex/com.android.art/lib64/libart.so (art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*) (.__uniq.165753521025965369065708152063621506277)+32)
  #22  pc 0x00000000003846a8  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (art_jni_trampoline+120)
  #23  pc 0x0000000000dd32b8  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run+136)
  #24  pc 0x0000000000ddef98  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (com.android.internal.os.ZygoteInit.main+3672)
  #25  pc 0x000000000033b680  /apex/com.android.art/lib64/libart.so (art_quick_invoke_static_stub+640)
  #26  pc 0x00000000004e2a90  /apex/com.android.art/lib64/libart.so (art::JValue art::InvokeWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+728)
  #27  pc 0x000000000057aa68  /apex/com.android.art/lib64/libart.so (art::JNI<true>::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+156)
  #28  pc 0x00000000000bdcd8  /system/lib64/libandroid_runtime.so (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+120)
  #29  pc 0x00000000000c9c94  /system/lib64/libandroid_runtime.so (android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool)+948)
  #30  pc 0x0000000000002560  /system/bin/app_process64 (main+1280)
  #31  pc 0x000000000004b630  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+96)

If using CocoaPods for Apple platforms, the project's Podfile.lock

Expand Podfile.lock snippet
```yml đź‘€ Replace this line with the contents of your Podfile.lock! ```
google-oss-bot commented 2 weeks ago

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

paulinon commented 2 weeks ago

Hi @shanemccartney,

Could you share the code you're using that references Cloud Storage? If you're able to reproduce the issue, could you also provide a minimal, reproducible example of your implementation so that we can identify what's causing this to happen?

shanemccartney commented 2 weeks ago

@paulinon, are you sure it's related to Storage?

Our assumption (perhaps wrongly) was that the issue was related to Real-time Database. The stack trace mentions Storage. We didn't know much about Firebase's internal operations.

Since we didn't use Storage services much in the game/app, it will be much easier to provide you with source code to help identify this issue.

Is there a best way for us to provide you with this source code?

shanemccartney commented 2 weeks ago

@paulinon Here is some code for now, potentially the issue is that the StorageProgress value is null.

This said its strange that this works on some devices and not others. See code with Storage used as is below, if you need to know some of the values of the constants let me know.

string remoteFilePath = string.Format(StoragePathRef.badges, playerBadgeOption.fileName);
string localFilePath = Path.Combine(Application.persistentDataPath, remoteFilePath);

StorageReference rootRef = FirebaseStorage.DefaultInstance.RootReference;
StorageReference badgeRef = rootRef.Child(remoteFilePath);

Directory.CreateDirectory(Path.GetDirectoryName(localFilePath));

Task getFileTask = badgeRef.GetFileAsync(AppConstants.UriFileScheme + localFilePath, null, cancellationToken).ContinueWithOnMainThread(task =>
{
    cancellationToken.ThrowIfCancellationRequested();

    if (task.IsCanceled) return;

    if (task.IsFaulted == false)
    {
        try
        {
            Texture2D result = LoadTexture(localFilePath);
            onComplete.Invoke(result);
        }
        catch
        {
            onError?.Invoke();
        }
    }
    else
    {
        onError?.Invoke();
    }
}, cancellationToken);
argzdev commented 1 week ago

Thanks for providing a code snippet, @shanemccartney. At first glance, it doesn't look like there's any apparent issue with the code that might trigger this issue. The StorageProgress instantiates with a default value of null, so I'm guessing this should be fine as well.

https://github.com/firebase/firebase-unity-sdk/blob/d8c1957ba2e58a5b51612b98f50a83d8eea87212/storage/src/StorageReference.cs#L719-L721

That said, it could be difficult for us to move this investigation forward without a proper way to reproduce the same behavior. Could you answer a few more questions below, it might give us a clue where to look for:

  1. Is this issue consistently reproducible?
  2. Which Android versions are affected?
  3. Is there certain steps to trigger this behavior? Or is it only upon GetFileAsync?
  4. Lastly, you've mentioned that the issue might be related to Real-time Database. Is there any reason why you think this might be the case?
shanemccartney commented 1 week ago

@paulinon Thanks, what we have done in the meantime is uploaded a build to Google Play with StorageProgress defined. I will let you know if this resolved the issue for us.

To answer your points:

  1. No it's not unfortunately. As I mentioned above so far it only seems to occur for specific Android devices i.e. "This does not seem to affect all users so far it seems to affect lower end Android devices like the Lenovo TB310FU with Android 13 (SDK 33)"
  2. See the above in point 1.
  3. We haven't been able to isolate these steps as its very much device or OS specific This error occurs when a request to Firebase is made during the experience of game play, and I know this from the logs. At first, we thought it would be something in the Real-time Database, as our implementation of this is quite complex. As you can see from my example with Storage, we don’t do anything else with this than so its pretty straight forward so would be unexpected to find an issue here.
  4. Refer to what I said in point 4 :)

Once again, thanks for your help and I really appreciate it. I will keep you posted on the new build. A simple solution to this problem would be to define StorageProgress, I get how this shouldn’t be needed. It's strange that this issue has been popping up for some users/players since this game has been live for quite some time and only recently have we updated Firebase for other reasons.

argzdev commented 1 week ago

Hi @shanemccartney, thanks for the extra details you've provided. We'll try to investigate this further on our side. Let me know if defining the StorageProgress works.

By the way, you've mentioned that the issue popped up after updating Firebase. Could you provide which version were you previously using? Perhaps we can check what changes were done which triggered this issue.

shanemccartney commented 1 week ago

@paulinon If it helps the issue happens in Firebase 11.7.0 through to version 11.9.0. This issue first happened in a version prior to those detailed above. So it’s potentially related to the Android OS. I say this because it appeared suddenly as an issue on a build this had been live for some time. Also the issue only affects a subset of Android users.

I will keep you updated, so far nothing logged in crashlytics. However its still only a few days for this build being live in A/B testing.

shanemccartney commented 1 week ago

@paulinon Unfortunately the same issue happened with defining StorageProgress within the A/B testing. In case this crash log helps it really seems the issue is within how Firebase handles this method for progress listeneing as our implementation of this is as so:

                StorageProgress<DownloadState> storageProgress = new StorageProgress<DownloadState>(state => { });

                badgeRef.GetFileAsync(AppConstants.UriFileScheme + localFilePath, storageProgress, cancellationToken).ContinueWithOnMainThread(task =>
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    if (task.IsCanceled) return;

                    if (task.IsFaulted == false)
                    {
                        try
                        {
                            Texture2D result = LoadTexture(localFilePath);
                            onComplete.Invoke(result);
                        }
                        catch
                        {
                            onError?.Invoke();
                        }
                    }
                    else
                    {
                        onError?.Invoke();
                    }
                }, cancellationToken);

Here is the crash log from a user with Android 11 (SDK 30) and a older device the Redmi Note 8 Pro

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 0, tid: 10710 >>> com.app <<<

backtrace:
  #00  pc 0x0000000000089ff4  /apex/com.android.runtime/lib64/bionic/libc.so (abort+180)
  #01  pc 0x00000000000edf04  /apex/com.android.runtime/lib64/bionic/libc.so (__fortify_fatal(char const*, ...)+124)
  #02  pc 0x00000000000ed4e4  /apex/com.android.runtime/lib64/bionic/libc.so (HandleUsingDestroyedMutex(pthread_mutex_t*, char const*)+52)
  #03  pc 0x00000000000ed338  /apex/com.android.runtime/lib64/bionic/libc.so (pthread_mutex_lock+160)
  #04  pc 0x00000000001a44f0  /data/app/~~RSZ3WoGsiD2uVFKlvVmRcQ==/com.app-YC41MVVdS7yjHCSZ4rQGiQ==/lib/arm64/libFirebaseCppApp-11_9_0.so (firebase::Mutex::Acquire()+8)
  #05  pc 0x0000000000249eec  /data/app/~~RSZ3WoGsiD2uVFKlvVmRcQ==/com.app-YC41MVVdS7yjHCSZ4rQGiQ==/lib/arm64/libFirebaseCppApp-11_9_0.so (firebase::storage::MonitorController::EventState::Schedule()+24)
  #06  pc 0x00000000002e6d7c  /data/app/~~RSZ3WoGsiD2uVFKlvVmRcQ==/com.app-YC41MVVdS7yjHCSZ4rQGiQ==/lib/arm64/libFirebaseCppApp-11_9_0.so (firebase::storage::internal::ControllerInternal::CppStorageListenerCallback(_JNIEnv*, _jclass*, long, long, _jobject*, unsigned char)+328)
  #07  pc 0x000000000013ded4  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+148)
  #08  pc 0x00000000001347e8  /apex/com.android.art/lib64/libart.so (art_quick_invoke_static_stub+568)
  #09  pc 0x00000000001aa804  /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+228)
  #10  pc 0x000000000031ed60  /apex/com.android.art/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+376)
  #11  pc 0x0000000000315fa8  /apex/com.android.art/lib64/libart.so (bool art::interpreter::DoCall<true, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+696)
  #12  pc 0x000000000068fd74  /apex/com.android.art/lib64/libart.so (MterpInvokeStaticRange+412)
  #13  pc 0x000000000012ec94  /apex/com.android.art/lib64/libart.so (mterp_op_invoke_static_range+20)
  #14  pc 0x0000000000000952  /data/data/com.app/cache/oat/arm64/storage_resources_lib.vdex (com.google.firebase.storage.internal.cpp.CppStorageListener.onProgress+46)
  #15  pc 0x000000000068b8b4  /apex/com.android.art/lib64/libart.so (MterpInvokeInterface+1812)
  #16  pc 0x000000000012ea14  /apex/com.android.art/lib64/libart.so (mterp_op_invoke_interface+20)
  #17  pc 0x000000000015369a  /data/app/~~RSZ3WoGsiD2uVFKlvVmRcQ==/com.app-YC41MVVdS7yjHCSZ4rQGiQ==/oat/arm64/base.vdex (com.google.firebase.storage.j.a+8)
  #18  pc 0x000000000068b8b4  /apex/com.android.art/lib64/libart.so (MterpInvokeInterface+1812)
  #19  pc 0x000000000012ea14  /apex/com.android.art/lib64/libart.so (mterp_op_invoke_interface+20)
  #20  pc 0x0000000000153f1c  /data/app/~~RSZ3WoGsiD2uVFKlvVmRcQ==/com.app-YC41MVVdS7yjHCSZ4rQGiQ==/oat/arm64/base.vdex (com.google.firebase.storage.TaskListenerImpl.f+4)
  #21  pc 0x000000000068c4f8  /apex/com.android.art/lib64/libart.so (MterpInvokeDirect+1248)
  #22  pc 0x000000000012e914  /apex/com.android.art/lib64/libart.so (mterp_op_invoke_direct+20)
  #23  pc 0x0000000000153e0e  /data/app/~~RSZ3WoGsiD2uVFKlvVmRcQ==/com.app-YC41MVVdS7yjHCSZ4rQGiQ==/oat/arm64/base.vdex (com.google.firebase.storage.TaskListenerImpl.c)
  #24  pc 0x000000000068cdd0  /apex/com.android.art/lib64/libart.so (MterpInvokeStatic+1224)
  #25  pc 0x000000000012e994  /apex/com.android.art/lib64/libart.so (mterp_op_invoke_static+20)
  #26  pc 0x0000000000153df6  /data/app/~~RSZ3WoGsiD2uVFKlvVmRcQ==/com.app-YC41MVVdS7yjHCSZ4rQGiQ==/oat/arm64/base.vdex (com.google.firebase.storage.z.run+12)
  #27  pc 0x000000000030c1f0  /apex/com.android.art/lib64/libart.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.10961521050880726714)+264)
  #28  pc 0x00000000006785d0  /apex/com.android.art/lib64/libart.so (artQuickToInterpreterBridge+776)
  #29  pc 0x000000000013dff8  /apex/com.android.art/lib64/libart.so (art_quick_to_interpreter_bridge+88)
  #30  pc 0x00000000006529ec  /system/framework/arm64/boot-framework.oat (android.os.Handler.dispatchMessage+76)
  #31  pc 0x00000000006560a0  /system/framework/arm64/boot-framework.oat (android.os.Looper.loop+1696)
  #32  pc 0x000000000040d758  /system/framework/arm64/boot-framework.oat (android.app.ActivityThread.main+1000)
  #33  pc 0x00000000001347e8  /apex/com.android.art/lib64/libart.so (art_quick_invoke_static_stub+568)
  #34  pc 0x00000000001aa804  /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+228)
  #35  pc 0x0000000000561094  /apex/com.android.art/lib64/libart.so (art::InvokeMethod(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned long)+1364)
  #36  pc 0x00000000004dfb60  /apex/com.android.art/lib64/libart.so (art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)+48)
  #37  pc 0x00000000000896f4  /apex/com.android.art/javalib/arm64/boot.oat (art_jni_trampoline+180)
  #38  pc 0x0000000000891968  /system/framework/arm64/boot-framework.oat (com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run+136)
  #39  pc 0x000000000089a0e0  /system/framework/arm64/boot-framework.oat (com.android.internal.os.ZygoteInit.main+2352)
  #40  pc 0x00000000001347e8  /apex/com.android.art/lib64/libart.so (art_quick_invoke_static_stub+568)
  #41  pc 0x00000000001aa804  /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+228)
  #42  pc 0x000000000055fab0  /apex/com.android.art/lib64/libart.so (art::JValue art::InvokeWithVarArgs<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, std::__va_list)+448)
  #43  pc 0x000000000055ff74  /apex/com.android.art/lib64/libart.so (art::JValue art::InvokeWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+92)
  #44  pc 0x00000000004424e4  /apex/com.android.art/lib64/libart.so (art::JNI<true>::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+652)
  #45  pc 0x000000000009d48c  /system/lib64/libandroid_runtime.so (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+124)
  #46  pc 0x00000000000a4c4c  /system/lib64/libandroid_runtime.so (android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool)+1020)
  #47  pc 0x000000000000357c  /system/bin/app_process64 (main+1332)
  #48  pc 0x00000000000854b4  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108)

With the message: FORTIFY: pthread_mutex_lock called on a destroyed mutex (0x)

Doing a quick prompt to Chat GPT to get some insight into the cause for an error related to HandleUsingDestroyedMutex, it seems to be related to one of these things within Firebase and listening for progress.


The error "HandleUsingDestroyedMutex" typically occurs when a program tries to access or manipulate a mutex (mutual exclusion) object that has already been destroyed or deallocated. A mutex is a synchronization primitive used to control access to shared resources in multithreaded programming environments.

Here are a few common reasons why this error might occur:

Double Destruction: If the mutex object is destroyed more than once (i.e., it is deallocated or freed after it has already been destroyed), attempts to access it will result in this error.

Access After Destruction: If a thread tries to access the mutex object after it has been destroyed or while it is in the process of being destroyed, this error can occur.

Concurrent Access: If multiple threads try to access the mutex object concurrently, and one of them destroys the mutex while others are still using it, this error can happen if proper synchronization mechanisms are not in place. To fix this error, you should review your code to ensure proper management of mutex objects. Make sure that mutexes are only destroyed when they are no longer needed and that all accesses to mutex objects are properly synchronized to prevent race conditions. Additionally, ensure that the mutex is not accessed after it has been destroyed. Debugging tools and techniques like logging, stack traces, and debugging sessions can help pinpoint the exact location and cause of this error in your code.


I only provided this in case its helpful, of course I know you most likely know this.

Of course its possible that the issue may not be even related to this but this detail could also help hone in and fix this issue more quickly. I only used Chat GPT in this instance as I am not very familiar with these types of errors.