// MODULE: cinterop // FILE: leakMemoryWithRunningThreadUnchecked.def --- void test_RunInNewThread(void (*)()); // FILE: leakMemoryWithRunningThreadUnchecked.h #ifdef __cplusplus extern "C" { #endif void test_RunInNewThread(void (*)()); #ifdef __cplusplus } #endif // FILE: leakMemoryWithRunningThreadUnchecked.cpp #include "leakMemoryWithRunningThreadUnchecked.h" #include #include extern "C" void test_RunInNewThread(void (*f)()) { std::atomic haveRun(false); std::thread t([f, &haveRun]() { f(); haveRun = true; while (true) {} }); t.detach(); while (!haveRun) {} } // MODULE: main(cinterop) // FILE: main.kt @file:OptIn( kotlin.experimental.ExperimentalNativeApi::class, kotlin.native.runtime.NativeRuntimeApi::class, kotlinx.cinterop.ExperimentalForeignApi::class ) import leakMemoryWithRunningThreadUnchecked.* import kotlin.concurrent.AtomicInt import kotlin.native.concurrent.* import kotlin.native.Platform import kotlin.test.* import kotlinx.cinterop.* val global = AtomicInt(0) fun ensureInititalized() { // Leak memory StableRef.create(Any()) global.value = 1 } fun main() { Platform.isMemoryLeakCheckerActive = true kotlin.native.runtime.Debugging.forceCheckedShutdown = false assertTrue(global.value == 0) // Created a thread, made sure Kotlin is initialized there. test_RunInNewThread(staticCFunction(::ensureInititalized)) assertTrue(global.value == 1) // Now exiting. With unchecked shutdown, we exit quietly, even though there're // unfinished threads with runtimes. }