简体   繁体   English

SoundPoolThread 通过 JNI 错误导致 SIGSEGV“访问已删除的全局引用”

[英]SoundPoolThread causing SIGSEGV via JNI ERROR "accessed deleted global reference"

My Android application (minSdkLevel: 2.2, targetSdkLevel: 3.0, testing on Nexus 7 with Android 4.2) does the following in the loading phase:我的 Android 应用程序(minSdkLevel:2.2,targetSdkLevel:3.0,在 Nexus 7 和 Android 4.2 上测试)在加载阶段执行以下操作:

  1. Creates a SoundPool and registers an OnLoadCompleteListener on it创建一个SoundPool并在其上注册一个OnLoadCompleteListener
  2. Starts loading sounds.开始加载声音。 SoundPool calls my callback method whenever a sound is loaded.每当加载声音时, SoundPool调用我的回调方法。
  3. If the loading process is interrupted by user, SoundPool.release() is called如果加载过程被用户中断,则调用SoundPool.release()
  4. (If release() was already called and a previously started sound loading completes, ie the system calls my callback, then my application detects that that my SoundPool is already null and ignores the callback, so it is safe). (如果release()已经被调用并且之前开始的声音加载完成,即系统调用我的回调,那么我的应用程序检测到我的SoundPool已经为null并忽略回调,所以它是安全的)。

Testing on a Nexus 7, the following error occured at 210ms after SoundPool.release() was called (logcat):在 Nexus 7 上进行测试,在调用SoundPool.release()SoundPool.release()出现以下错误(logcat):日志猫

Ie the event order was the following probably:即事件顺序可能如下:

  1. The system started to load sounds asynchronously due to my SoundPool.load(...) calls由于我的SoundPool.load(...)调用,系统开始异步加载声音
  2. I left the loading screen, so SoundPool.release() was called and SoundPool set to null我离开了加载屏幕,所以SoundPool.release()被调用并且SoundPool设置为null
  3. (?) The system completed an earlier sound loading completion callback, but encountered some error. (?) 系统完成了较早的声音加载完成回调,但遇到了一些错误。

I checked the Android source code and the JNI code for SoundPool.release() indeed deletes the SoundPool in JNI via DeleteGlobalRef .我检查了Android的源代码,并为JNI代码SoundPool.release()确实删除SoundPool通过JNI中DeleteGlobalRef It uses a weak reference to store the SoundPool reference on Java level.它使用弱引用在 Java 级别存储SoundPool引用。

I cannot reproduce the bug, probably because I can't reproduce the exact conditions due to nondeterminism.我无法重现该错误,可能是因为由于不确定性,我无法重现确切条件。 The system should correctly handle that a SoundPool might be released while it loads sounds asynchronously, but it seems under some rare circumstances, a bug appears.系统应该正确处理SoundPool在异步加载声音时可能会被释放的情况,但似乎在某些极少数情况下会出现错误。 (Note that my code releases SoundPool exactly once after a nullcheck, so the error is not in my code for sure). (请注意,我的代码版本SoundPool一个nullcheck后只出现一次,因此错误是不是在我的代码肯定)。

Any idea about why exactly does such an error occur in Android?知道为什么在 Android 中会发生这样的错误吗? Can my above suspicions be correct, in theory?从理论上讲,我的上述怀疑是否正确? How can I protect my application against this Android bug?如何保护我的应用程序免受此 Android 错误的影响? Maybe I can try setting in a boolean that the SoundPool should be released, wait until all callbacks returned, and then release it (based on this boolean) in the last callback?也许我可以尝试在一个布尔值中设置SoundPool应该被释放,等到所有回调返回,然后在最后一个回调中释放它(基于这个布尔值)? I can't think of any other workaround, but I would like to be sure that it will work, at least.我想不出任何其他解决方法,但我想确定它至少会起作用。

As you say, this appears to be a bug in Android due to a race condition.正如您所说,由于竞争条件,这似乎是 Android 中的一个错误。 As requested by user CommonsWare I opened a bug with the backtrace: http://code.google.com/p/android/issues/detail?id=53043根据用户 CommonsWare 的要求,我打开了一个带有回溯的错误: http : //code.google.com/p/android/issues/detail? id=53043

The offending code appears to be in Android's media/jni/soundpool/SoundPool.cpp which does:违规代码似乎在 Android 的 media/jni/soundpool/SoundPool.cpp 中,它执行以下操作:

void SoundPool::notify(SoundPoolEvent event)
{
    Mutex::Autolock lock(&mCallbackLock);
    if (mCallback != NULL) {
        mCallback(event, this, mUserData);
    }
}

Looks like mCallback is a Java object that can be deleted by the Garbage Collector, so when notify is called it tries to reference this object and the "accessed deleted global reference" crash happens.看起来 mCallback 是一个可以被垃圾收集器删除的 Java 对象,因此当调用 notify 时,它会尝试引用此对象,并且会发生“访问已删除的全局引用”崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM