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)
|
||||
// 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()"
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
@@ -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*);
|
||||
@@ -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);
|
||||
|}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import kotlinx.cinterop.*
|
||||
|
||||
import kotlin.native.CName
|
||||
import kotlin.native.concurrent.freeze
|
||||
|
||||
// Top level functions.
|
||||
fun hello() {
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
@@ -61,6 +65,9 @@ int main(void) {
|
||||
__ DisposeStablePointer(enum1.pinned);
|
||||
__ DisposeStablePointer(object1.pinned);
|
||||
|
||||
__ kotlin.root.setCErrorHandler(&errorHandler);
|
||||
__ kotlin.root.throwException();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -569,7 +569,6 @@ class ExceptionObjHolder {
|
||||
ObjHeader* obj_;
|
||||
};
|
||||
|
||||
|
||||
class KRefSharedHolder {
|
||||
public:
|
||||
inline ObjHeader** slotToInit() {
|
||||
|
||||
Reference in New Issue
Block a user