From 0c9caa06154cbeba501d08a8fe7860fc4ffdcd70 Mon Sep 17 00:00:00 2001 From: Emre Kultursay Date: Wed, 11 Mar 2026 16:28:49 -0700 Subject: [PATCH] Do not let the CPUTiming .so be unloaded Android Vulkan loader calls dlopen/dlclose/dlopen during the loading proces. This doesn't play nicely with Perfetto, so we get a crash. This change adds a keep-alive mechanism (taken from AGI) that prevents the unloading of the .so file. --- layersvt/CMakeLists.txt | 1 + layersvt/cputiming.cpp | 12 ++++++++++ layersvt/layer_keep_alive.cpp | 45 +++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 layersvt/layer_keep_alive.cpp diff --git a/layersvt/CMakeLists.txt b/layersvt/CMakeLists.txt index 393baef525..974a3e354c 100644 --- a/layersvt/CMakeLists.txt +++ b/layersvt/CMakeLists.txt @@ -133,6 +133,7 @@ if(BUILD_CPUTIMING) ../scripts/generators/cputiming_generator.py vk_layer_table.cpp vk_layer_table.h + layer_keep_alive.cpp json/VkLayer_CPUTiming.json.in ) diff --git a/layersvt/cputiming.cpp b/layersvt/cputiming.cpp index f6a07b503a..806a94f76a 100644 --- a/layersvt/cputiming.cpp +++ b/layersvt/cputiming.cpp @@ -17,6 +17,18 @@ #include "cputiming.h" +#if defined(__ANDROID__) +#include + +__attribute__((constructor)) static void cputiming_layer_init() { + __android_log_print(ANDROID_LOG_WARN, "CPUTiming", "dlopen: CPUTiming library"); +} + +__attribute__((destructor)) static void cputiming_layer_finish() { + __android_log_print(ANDROID_LOG_WARN, "CPUTiming", "dlclose: CPUTiming library"); +} +#endif + CpuTiming& CpuTiming::Get() { static CpuTiming instance; return instance; diff --git a/layersvt/layer_keep_alive.cpp b/layersvt/layer_keep_alive.cpp new file mode 100644 index 0000000000..c375f0b637 --- /dev/null +++ b/layersvt/layer_keep_alive.cpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2015-2023 The Khronos Group Inc. + * Copyright (c) 2015-2023 Valve Corporation + * Copyright (c) 2015-2023 LunarG, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(__ANDROID__) +#include + +namespace { + +// Anonymous namespace function is NOT exported, keeping it local to each shared object. +// We use a constructor attribute to trigger it when the library is loaded/opened. +void layer_keep_alive_func(); + +class KeepAlive { + public: + KeepAlive() { + Dl_info info; + // Attempt to find the filename of the library containing this code. + if (dladdr((void*)&layer_keep_alive_func, &info)) { + // Re-open with RTLD_NODELETE to force the library to stay resident. + dlopen(info.dli_fname, RTLD_NODELETE); + } + } +}; + +__attribute__((constructor)) void layer_keep_alive_func() { + static KeepAlive k; + (void)k; +} + +} // namespace +#endif