diff --git a/runtime/src/main/cpp/Runtime.cpp b/runtime/src/main/cpp/Runtime.cpp index ed4cad9f9af..55d07278b4a 100644 --- a/runtime/src/main/cpp/Runtime.cpp +++ b/runtime/src/main/cpp/Runtime.cpp @@ -265,4 +265,8 @@ KBoolean Konan_Platform_isDebugBinary() { return KonanNeedDebugInfo ? true : false; } +void Kotlin_zeroOutTLSGlobals() { + InitOrDeinitGlobalVariables(DEINIT_THREAD_LOCAL_GLOBALS); +} + } // extern "C" diff --git a/runtime/src/main/cpp/Runtime.h b/runtime/src/main/cpp/Runtime.h index 30ddcb2ccc3..68a3392f52f 100644 --- a/runtime/src/main/cpp/Runtime.h +++ b/runtime/src/main/cpp/Runtime.h @@ -50,6 +50,9 @@ bool Kotlin_hasRuntime(); // Appends given node to an initializer list. void AppendToInitializersTail(struct InitNode*); +// Zero out all Kotlin thread local globals. +void Kotlin_zeroOutTLSGlobals(); + #ifdef __cplusplus } #endif diff --git a/runtime/src/main/cpp/Worker.cpp b/runtime/src/main/cpp/Worker.cpp index 51d46aae49d..467f831ff24 100644 --- a/runtime/src/main/cpp/Worker.cpp +++ b/runtime/src/main/cpp/Worker.cpp @@ -466,6 +466,10 @@ void* workerRoutine(void* argument) { if (worker->processQueueElement(true) == JOB_TERMINATE) break; } while (true); + // Runtime deinit callback could be called when TLS is already zeroed out, so clear memory + // here explicitly. to make sure leak detector properly works. + Kotlin_zeroOutTLSGlobals(); + return nullptr; }