From c582612bd758cc3ed6b0d8762d8f4c2f94276a2d Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Thu, 10 Dec 2020 09:52:31 +0300 Subject: [PATCH] Restore runtimeState value in deinitRuntime (#4587) --- .../backend.native/tests/build.gradle | 23 +++++++++++++++++++ .../tests/interop/objc/kt42172/main.kt | 18 +++++++++++++++ .../tests/interop/objc/kt42172/objclib.def | 3 +++ .../tests/interop/objc/kt42172/objclib.h | 9 ++++++++ .../tests/interop/objc/kt42172/objclib.m | 19 +++++++++++++++ .../runtime/src/main/cpp/Runtime.cpp | 7 +++--- 6 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 kotlin-native/backend.native/tests/interop/objc/kt42172/main.kt create mode 100644 kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.def create mode 100644 kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.h create mode 100644 kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.m diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index a38d5dfc86e..e497fc168ee 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -3813,6 +3813,10 @@ if (PlatformInfo.isAppleTarget(project)) { createInterop("objcKt43517") { it.defFile 'framework/kt43517/kt43517.def' } + createInterop("objc_kt42172") { + it.defFile 'interop/objc/kt42172/objclib.def' + it.headers "$projectDir/interop/objc/kt42172/objclib.h" + } } createInterop("withSpaces") { @@ -4281,6 +4285,25 @@ if (PlatformInfo.isAppleTarget(project)) { it.contains("isObjectAliveShouldCrash") // And should contain stack trace. } } + + interopTest("interop_objc_kt42172") { + source = "interop/objc/kt42172/main.kt" + interop = "objc_kt42172" + flags = ['-Xopt-in=kotlin.native.internal.InternalForKotlinNative'] + goldValue = 'Executed finalizer\n' + + doBeforeBuild { + mkdir(buildDir) + execKonanClang(project.target) { + args "$projectDir/interop/objc/kt42172/objclib.m" + args "-lobjc", '-fobjc-arc' + args '-fPIC', '-shared', '-o', "$buildDir/libobjc_kt42172.dylib" + } + if (project.target instanceof KonanTarget.IOS_X64) { + UtilsKt.codesign(project, "$buildDir/libobjc_kt42172.dylib") + } + } + } } standaloneTest("jsinterop_math") { diff --git a/kotlin-native/backend.native/tests/interop/objc/kt42172/main.kt b/kotlin-native/backend.native/tests/interop/objc/kt42172/main.kt new file mode 100644 index 00000000000..4e1f9cc1b2d --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt42172/main.kt @@ -0,0 +1,18 @@ +import objclib.* +import kotlin.native.concurrent.* +import kotlinx.cinterop.* + +fun main() { + val worker = Worker.start() + worker.execute(TransferMode.SAFE, {}) { + val withFinalizer = WithFinalizer() + val finalizer: Finalizer = staticCFunction { ptr: COpaquePointer? -> + ptr?.asStableRef()?.dispose() + println("Executed finalizer") + } + val arg = StableRef.create(Any()).asCPointer() + withFinalizer.setFinalizer(finalizer, arg) + }.result + worker.requestTermination().result + waitWorkerTermination(worker) +} diff --git a/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.def b/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.def new file mode 100644 index 00000000000..65bbb0a8ba1 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.def @@ -0,0 +1,3 @@ +language = Objective-C +headerFilter = **/objclib.h +linkerOpts = -lobjc_kt42172 diff --git a/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.h b/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.h new file mode 100644 index 00000000000..77a6036a60f --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.h @@ -0,0 +1,9 @@ +#import + +typedef void (*Finalizer)(void*); + +@interface WithFinalizer : NSObject + +- (void)setFinalizer:(Finalizer)finalizer arg:(void*)arg; + +@end diff --git a/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.m b/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.m new file mode 100644 index 00000000000..856eede0330 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/objc/kt42172/objclib.m @@ -0,0 +1,19 @@ +#include "objclib.h" + +@implementation WithFinalizer { + Finalizer finalizer_; + void* arg_; +} + +- (void)dealloc { + if (finalizer_) { + finalizer_(arg_); + } +} + +- (void)setFinalizer:(Finalizer)finalizer arg:(void*)arg { + finalizer_ = finalizer; + arg_ = arg; +} + +@end diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.cpp b/kotlin-native/runtime/src/main/cpp/Runtime.cpp index 9a1f6feb01d..faa29a629de 100644 --- a/kotlin-native/runtime/src/main/cpp/Runtime.cpp +++ b/kotlin-native/runtime/src/main/cpp/Runtime.cpp @@ -140,7 +140,9 @@ RuntimeState* initRuntime() { void deinitRuntime(RuntimeState* state, bool destroyRuntime) { RuntimeAssert(state->status == RuntimeStatus::kRunning, "Runtime must be in the running state"); state->status = RuntimeStatus::kDestroying; - // This may be called after TLS is zeroed out, so ::memoryState in Memory cannot be trusted. + // This may be called after TLS is zeroed out, so ::runtimeState and ::memoryState in Memory cannot be trusted. + // TODO: This may in fact reallocate TLS without guarantees that it'll be deallocated again. + ::runtimeState = state; RestoreMemory(state->memoryState); bool lastRuntime = atomicAdd(&aliveRuntimesCount, -1) == 0; switch (Kotlin_getDestroyRuntimeMode()) { @@ -159,6 +161,7 @@ void deinitRuntime(RuntimeState* state, bool destroyRuntime) { DeinitMemory(state->memoryState, destroyRuntime); konanDestructInstance(state); WorkerDestroyThreadDataIfNeeded(workerId); + ::runtimeState = kInvalidRuntime; } void Kotlin_deinitRuntimeCallback(void* argument) { @@ -191,7 +194,6 @@ void Kotlin_initRuntimeIfNeeded() { void Kotlin_deinitRuntimeIfNeeded() { if (isValidRuntime()) { deinitRuntime(::runtimeState, false); - ::runtimeState = kInvalidRuntime; } } @@ -249,7 +251,6 @@ void Kotlin_shutdownRuntime() { } deinitRuntime(runtime, canDestroyRuntime); - ::runtimeState = kInvalidRuntime; } KInt Konan_Platform_canAccessUnaligned() {