Custom exception hook in reverse C interop (#2946)
This commit is contained in:
+19
@@ -432,6 +432,7 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
val isStringReturned = owner.isMappedToString(cfunction[0].second)
|
val isStringReturned = owner.isMappedToString(cfunction[0].second)
|
||||||
// TODO: do we really need that in every function?
|
// TODO: do we really need that in every function?
|
||||||
builder.append(" Kotlin_initRuntimeIfNeeded();\n")
|
builder.append(" Kotlin_initRuntimeIfNeeded();\n")
|
||||||
|
builder.append(" try {\n")
|
||||||
if (isObjectReturned || isStringReturned) {
|
if (isObjectReturned || isStringReturned) {
|
||||||
builder.append(" KObjHolder result_holder;\n")
|
builder.append(" KObjHolder result_holder;\n")
|
||||||
args += "result_holder.slot()"
|
args += "result_holder.slot()"
|
||||||
@@ -455,6 +456,8 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
"result", cfunction[0].second, Direction.KOTLIN_TO_C, builder)
|
"result", cfunction[0].second, Direction.KOTLIN_TO_C, builder)
|
||||||
builder.append(" return $result;\n")
|
builder.append(" return $result;\n")
|
||||||
}
|
}
|
||||||
|
builder.append(" } catch (ExceptionObjHolder& e) { TerminateWithUnhandledException(e.obj()); } \n")
|
||||||
|
|
||||||
builder.append("}\n")
|
builder.append("}\n")
|
||||||
|
|
||||||
return builder.toString()
|
return builder.toString()
|
||||||
@@ -885,6 +888,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
|
|
|
|
||||||
|#define RUNTIME_NOTHROW __attribute__((nothrow))
|
|#define RUNTIME_NOTHROW __attribute__((nothrow))
|
||||||
|#define RUNTIME_USED __attribute__((used))
|
|#define RUNTIME_USED __attribute__((used))
|
||||||
|
|#define RUNTIME_NORETURN __attribute__((noreturn))
|
||||||
|
|
|
|
||||||
|extern "C" {
|
|extern "C" {
|
||||||
|void UpdateHeapRef(KObjHeader**, const KObjHeader*) RUNTIME_NOTHROW;
|
|void UpdateHeapRef(KObjHeader**, const KObjHeader*) RUNTIME_NOTHROW;
|
||||||
@@ -897,6 +901,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
|void EnterFrame(KObjHeader** start, int parameters, int count) RUNTIME_NOTHROW;
|
|void EnterFrame(KObjHeader** start, int parameters, int count) RUNTIME_NOTHROW;
|
||||||
|void LeaveFrame(KObjHeader** start, int parameters, int count) RUNTIME_NOTHROW;
|
|void LeaveFrame(KObjHeader** start, int parameters, int count) RUNTIME_NOTHROW;
|
||||||
|void Kotlin_initRuntimeIfNeeded();
|
|void Kotlin_initRuntimeIfNeeded();
|
||||||
|
|void TerminateWithUnhandledException(KObjHeader*) RUNTIME_NORETURN;
|
||||||
|
|
|
|
||||||
|KObjHeader* CreateStringFromCString(const char*, KObjHeader**);
|
|KObjHeader* CreateStringFromCString(const char*, KObjHeader**);
|
||||||
|char* CreateCStringFromString(const KObjHeader*);
|
|char* CreateCStringFromString(const KObjHeader*);
|
||||||
@@ -930,6 +935,20 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
|
|
|
|
||||||
| KObjHeader** frame() { return reinterpret_cast<KObjHeader**>(&frame_); }
|
| 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) {
|
|static void DisposeStablePointerImpl(${prefix}_KNativePtr ptr) {
|
||||||
| DisposeStablePointer(ptr);
|
| DisposeStablePointer(ptr);
|
||||||
|}
|
|}
|
||||||
|
|||||||
@@ -3297,7 +3297,8 @@ task produce_dynamic(type: DynamicKonanTest) {
|
|||||||
"object = 42\n" +
|
"object = 42\n" +
|
||||||
"singleton = I am single\n" +
|
"singleton = I am single\n" +
|
||||||
"mutable = foo\n" +
|
"mutable = foo\n" +
|
||||||
"topLevel = 777 3\n"
|
"topLevel = 777 3\n" +
|
||||||
|
"Error handler: kotlin.Error: Expected error\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
task library_mismatch(type: RunStandaloneKonanTest) {
|
task library_mismatch(type: RunStandaloneKonanTest) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
|
|
||||||
import kotlin.native.CName
|
import kotlin.native.CName
|
||||||
|
import kotlin.native.concurrent.freeze
|
||||||
|
|
||||||
// Top level functions.
|
// Top level functions.
|
||||||
fun hello() {
|
fun hello() {
|
||||||
@@ -96,3 +97,17 @@ fun useInlineClasses(ic1: IC1, ic2: IC2, ic3: IC3) {
|
|||||||
assert(ic2.value == "bar")
|
assert(ic2.value == "bar")
|
||||||
assert(ic3.value is Base)
|
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")
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
#define T_(x) testlib_kref_ ## x
|
#define T_(x) testlib_kref_ ## x
|
||||||
#define CAST(T, v) testlib_kref_ ## T { .pinned = v }
|
#define CAST(T, v) testlib_kref_ ## T { .pinned = v }
|
||||||
|
|
||||||
|
void errorHandler(const char* str) {
|
||||||
|
printf("Error handler: %s\n", str);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
T_(Singleton) singleton = __ kotlin.root.Singleton._instance();
|
T_(Singleton) singleton = __ kotlin.root.Singleton._instance();
|
||||||
T_(Base) base = __ kotlin.root.Base.Base();
|
T_(Base) base = __ kotlin.root.Base.Base();
|
||||||
@@ -61,6 +65,9 @@ int main(void) {
|
|||||||
__ DisposeStablePointer(enum1.pinned);
|
__ DisposeStablePointer(enum1.pinned);
|
||||||
__ DisposeStablePointer(object1.pinned);
|
__ DisposeStablePointer(object1.pinned);
|
||||||
|
|
||||||
|
__ kotlin.root.setCErrorHandler(&errorHandler);
|
||||||
|
__ kotlin.root.throwException();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -569,7 +569,6 @@ class ExceptionObjHolder {
|
|||||||
ObjHeader* obj_;
|
ObjHeader* obj_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class KRefSharedHolder {
|
class KRefSharedHolder {
|
||||||
public:
|
public:
|
||||||
inline ObjHeader** slotToInit() {
|
inline ObjHeader** slotToInit() {
|
||||||
|
|||||||
Reference in New Issue
Block a user