From f377fd47a3cf191c9c8c5c1e1b50812756cd47dc Mon Sep 17 00:00:00 2001 From: Tobrun Date: Thu, 4 Jun 2020 09:04:57 +0200 Subject: [PATCH] [renderer] gracefully ignore exceptions thrown in the android map renderer (#411) --- MapboxGLAndroidSDK/src/cpp/map_renderer.cpp | 99 +++++++++++++-------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/MapboxGLAndroidSDK/src/cpp/map_renderer.cpp b/MapboxGLAndroidSDK/src/cpp/map_renderer.cpp index d99c3730b..07a66f226 100644 --- a/MapboxGLAndroidSDK/src/cpp/map_renderer.cpp +++ b/MapboxGLAndroidSDK/src/cpp/map_renderer.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -37,17 +38,21 @@ std::shared_ptr MapRenderer::MailboxData::getMailbox() const noexcept { MapRenderer::~MapRenderer() = default; void MapRenderer::reset() { - destroyed = true; + try { + destroyed = true; - if (renderer) { - // Make sure to destroy the renderer on the GL Thread - auto self = ActorRef(*this, mailboxData.getMailbox()); - self.ask(&MapRenderer::resetRenderer).wait(); + if (renderer) { + // Make sure to destroy the renderer on the GL Thread + auto self = ActorRef(*this, mailboxData.getMailbox()); + self.ask(&MapRenderer::resetRenderer).wait(); + } + + // Lock to make sure there is no concurrent initialisation on the gl thread + std::lock_guard lock(initialisationMutex); + rendererObserver.reset(); + } catch (const std::exception& exception) { + Log::Error(Event::Android, "MapRenderer::reset failed: %s", exception.what()); } - - // Lock to make sure there is no concurrent initialisation on the gl thread - std::lock_guard lock(initialisationMutex); - rendererObserver.reset(); } ActorRef MapRenderer::actor() const { @@ -55,51 +60,67 @@ ActorRef MapRenderer::actor() const { } void MapRenderer::schedule(std::function scheduled) { - // Create a runnable - android::UniqueEnv _env = android::AttachEnv(); - auto runnable = std::make_unique(*_env, std::move(scheduled)); + try { + // Create a runnable + android::UniqueEnv _env = android::AttachEnv(); + auto runnable = std::make_unique(*_env, std::move(scheduled)); - // Obtain ownership of the peer (gets transferred to the MapRenderer on the JVM for later GC) - auto peer = runnable->peer(); + // Obtain ownership of the peer (gets transferred to the MapRenderer on the JVM for later GC) + auto peer = runnable->peer(); - // Queue the event on the Java Peer - static auto& javaClass = jni::Class::Singleton(*_env); - static auto queueEvent = javaClass.GetMethod)>(*_env, "queueEvent"); - auto weakReference = javaPeer.get(*_env); - if (weakReference) { - weakReference.Call(*_env, queueEvent, peer); + // Queue the event on the Java Peer + static auto& javaClass = jni::Class::Singleton(*_env); + static auto queueEvent = javaClass.GetMethod)>(*_env, "queueEvent"); + auto weakReference = javaPeer.get(*_env); + if (weakReference) { + weakReference.Call(*_env, queueEvent, peer); + } + + // Release the c++ peer as it will be destroyed on GC of the Java Peer + runnable.release(); + } catch (const std::exception& exception) { + Log::Error(Event::Android, "MapRenderer::schedule failed: %s", exception.what()); } - - // Release the c++ peer as it will be destroyed on GC of the Java Peer - runnable.release(); } void MapRenderer::requestRender() { - android::UniqueEnv _env = android::AttachEnv(); - static auto& javaClass = jni::Class::Singleton(*_env); - static auto onInvalidate = javaClass.GetMethod(*_env, "requestRender"); - auto weakReference = javaPeer.get(*_env); - if (weakReference) { - weakReference.Call(*_env, onInvalidate); + try { + android::UniqueEnv _env = android::AttachEnv(); + static auto& javaClass = jni::Class::Singleton(*_env); + static auto onInvalidate = javaClass.GetMethod(*_env, "requestRender"); + auto weakReference = javaPeer.get(*_env); + if (weakReference) { + weakReference.Call(*_env, onInvalidate); + } + } catch (const std::exception& exception) { + Log::Error(Event::Android, "MapRenderer::requestRender failed: %s", exception.what()); } } void MapRenderer::update(std::shared_ptr params) { - // Lock on the parameters - std::lock_guard lock(updateMutex); - updateParameters = std::move(params); + try { + // Lock on the parameters + std::lock_guard lock(updateMutex); + updateParameters = std::move(params); + } catch (const std::exception& exception) { + Log::Error(Event::Android, "MapRenderer::update failed: %s", exception.what()); + } } void MapRenderer::setObserver(std::shared_ptr _rendererObserver) { - // Lock as the initialization can come from the main thread or the GL thread first - std::lock_guard lock(initialisationMutex); + try { + // Lock as the initialization can come from the main thread or the GL thread first + std::lock_guard lock(initialisationMutex); - rendererObserver = std::move(_rendererObserver); + rendererObserver = std::move(_rendererObserver); - // Set the new observer on the Renderer implementation - if (renderer) { - renderer->setObserver(rendererObserver.get()); + // Set the new observer on the Renderer implementation + if (renderer) { + renderer->setObserver(rendererObserver.get()); + } + } catch (const std::exception& exception) { + Log::Error(Event::Android, "MapRenderer::setObserver failed: %s", exception.what()); } }