Skip to content

Commit

Permalink
Custom exception hook in reverse C interop (JetBrains#2946)
Browse files Browse the repository at this point in the history
  • Loading branch information
olonho authored May 14, 2019
1 parent e553684 commit 019e7b1
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ private class ExportedElement(val kind: ElementKind,
val isStringReturned = owner.isMappedToString(cfunction[0].second)
// TODO: do we really need that in every function?
builder.append(" Kotlin_initRuntimeIfNeeded();\n")
builder.append(" try {\n")
if (isObjectReturned || isStringReturned) {
builder.append(" KObjHolder result_holder;\n")
args += "result_holder.slot()"
Expand All @@ -455,6 +456,8 @@ private class ExportedElement(val kind: ElementKind,
"result", cfunction[0].second, Direction.KOTLIN_TO_C, builder)
builder.append(" return $result;\n")
}
builder.append(" } catch (ExceptionObjHolder& e) { TerminateWithUnhandledException(e.obj()); } \n")

builder.append("}\n")

return builder.toString()
Expand Down Expand Up @@ -885,6 +888,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|#define RUNTIME_NOTHROW __attribute__((nothrow))
|#define RUNTIME_USED __attribute__((used))
|#define RUNTIME_NORETURN __attribute__((noreturn))
|
|extern "C" {
|void UpdateHeapRef(KObjHeader**, const KObjHeader*) RUNTIME_NOTHROW;
Expand All @@ -897,6 +901,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|void EnterFrame(KObjHeader** start, int parameters, int count) RUNTIME_NOTHROW;
|void LeaveFrame(KObjHeader** start, int parameters, int count) RUNTIME_NOTHROW;
|void Kotlin_initRuntimeIfNeeded();
|void TerminateWithUnhandledException(KObjHeader*) RUNTIME_NORETURN;
|
|KObjHeader* CreateStringFromCString(const char*, KObjHeader**);
|char* CreateCStringFromString(const KObjHeader*);
Expand Down Expand Up @@ -930,6 +935,20 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
| KObjHeader** frame() { return reinterpret_cast<KObjHeader**>(&frame_); }
|};
|
|class ExceptionObjHolder {
| public:
| explicit ExceptionObjHolder(const KObjHeader* obj): obj_(nullptr) {
| ::UpdateHeapRef(&obj_, obj);
| }
| ~ExceptionObjHolder() {
| UpdateHeapRef(&obj_, nullptr);
| }
| KObjHeader* obj() { return obj_; }
| private:
| KObjHeader* obj_;
|};
|
|static void DisposeStablePointerImpl(${prefix}_KNativePtr ptr) {
| DisposeStablePointer(ptr);
|}
Expand Down
3 changes: 2 additions & 1 deletion backend.native/tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3297,7 +3297,8 @@ task produce_dynamic(type: DynamicKonanTest) {
"object = 42\n" +
"singleton = I am single\n" +
"mutable = foo\n" +
"topLevel = 777 3\n"
"topLevel = 777 3\n" +
"Error handler: kotlin.Error: Expected error\n"
}

task library_mismatch(type: RunStandaloneKonanTest) {
Expand Down
15 changes: 15 additions & 0 deletions backend.native/tests/produce_dynamic/simple/hello.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import kotlinx.cinterop.*

import kotlin.native.CName
import kotlin.native.concurrent.freeze

// Top level functions.
fun hello() {
Expand Down Expand Up @@ -96,3 +97,17 @@ fun useInlineClasses(ic1: IC1, ic2: IC2, ic3: IC3) {
assert(ic2.value == "bar")
assert(ic3.value is Base)
}

fun setCErrorHandler(callback: CPointer<CFunction<(CPointer<ByteVar>) -> Unit>>?) {
setUnhandledExceptionHook({
throwable: Throwable ->
memScoped {
callback!!(throwable.toString().cstr.ptr)
}
kotlin.system.exitProcess(0)
}.freeze())
}

fun throwException() {
throw Error("Expected error")
}
7 changes: 7 additions & 0 deletions backend.native/tests/produce_dynamic/simple/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
#define T_(x) testlib_kref_ ## x
#define CAST(T, v) testlib_kref_ ## T { .pinned = v }

void errorHandler(const char* str) {
printf("Error handler: %s\n", str);
}

int main(void) {
T_(Singleton) singleton = __ kotlin.root.Singleton._instance();
T_(Base) base = __ kotlin.root.Base.Base();
Expand Down Expand Up @@ -61,6 +65,9 @@ int main(void) {
__ DisposeStablePointer(enum1.pinned);
__ DisposeStablePointer(object1.pinned);

__ kotlin.root.setCErrorHandler(&errorHandler);
__ kotlin.root.throwException();

return 0;
}

1 change: 0 additions & 1 deletion runtime/src/main/cpp/Memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,6 @@ class ExceptionObjHolder {
ObjHeader* obj_;
};


class KRefSharedHolder {
public:
inline ObjHeader** slotToInit() {
Expand Down

0 comments on commit 019e7b1

Please sign in to comment.