Open shanemccartney opened 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.
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?
@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?
@paulinon Here is some code for now, potentially the issue is that the StorageProgress
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);
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.
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:
GetFileAsync
?@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:
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.
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.
@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.
@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.
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
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! ```