From f24db4633eb6bac06252c9d4ce2976fb2b2dcbde Mon Sep 17 00:00:00 2001 From: Sungun Park Date: Wed, 18 Mar 2026 19:26:58 -0700 Subject: [PATCH] Fix crash in OpenGLDriver::destroyStream (#9801) Fixes a SIGSEGV crash that occurs during `ExternalStreamManagerAndroid::release()` when users provide a custom Platform instance during Engine creation. When a custom Platform is used, ExternalStreamManagerAndroid is instantiated on the application's thread. Its constructor was caching a C++ reference (`VirtualMachineEnv& mVm`) to the `thread_local` VirtualMachineEnv instance belonging to the application thread. Later, when the Filament backend thread executed `release()`, it accessed this cached reference. This caused the backend thread to retrieve the `JNIEnv*` from the application thread's `thread_local` instance, and subsequently call `env->DeleteGlobalRef()`. A thread must use its own `JNIEnv` pointer, so using the application thread's pointer from the backend thread resulted in a crash. BUGS=[489814416] --- .../backend/platforms/PlatformEGLAndroid.h | 2 +- .../ExternalStreamManagerAndroid.cpp | 3 ++ .../opengl/platforms/PlatformEGLAndroid.cpp | 30 +++++++++++++------ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/filament/backend/include/backend/platforms/PlatformEGLAndroid.h b/filament/backend/include/backend/platforms/PlatformEGLAndroid.h index 9bf8aaae88..c47bd823df 100644 --- a/filament/backend/include/backend/platforms/PlatformEGLAndroid.h +++ b/filament/backend/include/backend/platforms/PlatformEGLAndroid.h @@ -185,7 +185,7 @@ private: }; int mOSVersion; - ExternalStreamManagerAndroid& mExternalStreamManager; + ExternalStreamManagerAndroid* mExternalStreamManager = nullptr; AndroidDetails& mAndroidDetails; utils::PerformanceHintManager mPerformanceHintManager; utils::PerformanceHintManager::Session mPerformanceHintSession; diff --git a/filament/backend/src/opengl/platforms/ExternalStreamManagerAndroid.cpp b/filament/backend/src/opengl/platforms/ExternalStreamManagerAndroid.cpp index 14954672d7..4a5db90596 100644 --- a/filament/backend/src/opengl/platforms/ExternalStreamManagerAndroid.cpp +++ b/filament/backend/src/opengl/platforms/ExternalStreamManagerAndroid.cpp @@ -80,6 +80,9 @@ JNIEnv* ExternalStreamManagerAndroid::getEnvironmentSlow() noexcept { Stream* ExternalStreamManagerAndroid::acquire(jobject surfaceTexture) noexcept { // note: This is called on the application thread (not the GL thread) + // The application thread *MUST* be attached to the JVM to pass the java 'surfaceTexture' down + // to filament natively, so we are guaranteed to get a valid JNIEnv from getThreadEnvironment() + // without needing AttachCurrentThread. JNIEnv* env = VirtualMachineEnv::getThreadEnvironment(); if (!env) { return nullptr; // this should not happen diff --git a/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp b/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp index 0ca672b455..0371b1a846 100644 --- a/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp +++ b/filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp @@ -120,8 +120,7 @@ struct PlatformEGLAndroid::AndroidDetails { // --------------------------------------------------------------------------------------------- PlatformEGLAndroid::PlatformEGLAndroid() noexcept - : mExternalStreamManager(ExternalStreamManagerAndroid::create()), - mAndroidDetails(*(new(std::nothrow) AndroidDetails{})) { + : mAndroidDetails(*(new(std::nothrow) AndroidDetails{})) { mOSVersion = android_get_device_api_level(); if (mOSVersion < 0) { mOSVersion = __ANDROID_API_FUTURE__; @@ -135,7 +134,10 @@ PlatformEGLAndroid::~PlatformEGLAndroid() noexcept { void PlatformEGLAndroid::terminate() noexcept { mPerformanceHintManager.terminate(); mAndroidDetails.androidFrameCallback.terminate(); - ExternalStreamManagerAndroid::destroy(&mExternalStreamManager); + if (mExternalStreamManager) { + ExternalStreamManagerAndroid::destroy(mExternalStreamManager); + mExternalStreamManager = nullptr; + } PlatformEGL::terminate(); } @@ -225,6 +227,10 @@ Driver* PlatformEGLAndroid::createDriver(void* sharedContext, mPerformanceHintSession = PerformanceHintManager::Session{ mPerformanceHintManager, &tid, 1, 16'666'667 }; + mExternalStreamManager = &ExternalStreamManagerAndroid::create(); + FILAMENT_CHECK_POSTCONDITION(mExternalStreamManager) + << "Failed to create ExternalStreamManagerAndroid"; + Driver* driver = PlatformEGL::createDriver(sharedContext, driverConfig); auto const extensions = GLUtils::split(eglQueryString(getEglDisplay(), EGL_EXTENSIONS)); @@ -611,11 +617,13 @@ void PlatformEGLAndroid::setPresentationTime(int64_t const presentationTimeInNan } Platform::Stream* PlatformEGLAndroid::createStream(void* nativeStream) noexcept { - return mExternalStreamManager.acquire(static_cast(nativeStream)); + assert_invariant(mExternalStreamManager); + return mExternalStreamManager->acquire(static_cast(nativeStream)); } void PlatformEGLAndroid::destroyStream(Stream* stream) noexcept { - mExternalStreamManager.release(stream); + assert_invariant(mExternalStreamManager); + mExternalStreamManager->release(stream); } Platform::Sync* PlatformEGLAndroid::createSync() noexcept { @@ -667,19 +675,23 @@ void PlatformEGLAndroid::destroySync(Sync* sync) noexcept { } void PlatformEGLAndroid::attach(Stream* stream, intptr_t const tname) noexcept { - mExternalStreamManager.attach(stream, tname); + assert_invariant(mExternalStreamManager); + mExternalStreamManager->attach(stream, tname); } void PlatformEGLAndroid::detach(Stream* stream) noexcept { - mExternalStreamManager.detach(stream); + assert_invariant(mExternalStreamManager); + mExternalStreamManager->detach(stream); } void PlatformEGLAndroid::updateTexImage(Stream* stream, int64_t* timestamp) noexcept { - mExternalStreamManager.updateTexImage(stream, timestamp); + assert_invariant(mExternalStreamManager); + mExternalStreamManager->updateTexImage(stream, timestamp); } math::mat3f PlatformEGLAndroid::getTransformMatrix(Stream* stream) noexcept { - return mExternalStreamManager.getTransformMatrix(stream); + assert_invariant(mExternalStreamManager); + return mExternalStreamManager->getTransformMatrix(stream); } int PlatformEGLAndroid::getOSVersion() const noexcept {