diff --git a/runtime/src/main/cpp/Exceptions.cpp b/runtime/src/main/cpp/Exceptions.cpp index 30b12653bf3..746a6205eab 100644 --- a/runtime/src/main/cpp/Exceptions.cpp +++ b/runtime/src/main/cpp/Exceptions.cpp @@ -190,12 +190,17 @@ void ThrowException(KRef exception) { #endif } +void ReportUnhandledException(KRef e); + +RUNTIME_NORETURN void TerminateWithUnhandledException(KRef e) { + ReportUnhandledException(e); + konan::abort(); +} + // Some libstdc++-based targets has limited support for std::current_exception and other C++11 functions. // This restriction can be lifted later when toolchains will be updated. #if KONAN_HAS_CXX11_EXCEPTION_FUNCTIONS -void ReportUnhandledException(KRef e); - static void (*oldTerminateHandler)() = nullptr; static void KonanTerminateHandler() { @@ -208,8 +213,7 @@ static void KonanTerminateHandler() { try { std::rethrow_exception(currentException); } catch (ObjHolder& e) { - ReportUnhandledException(e.obj()); - konan::abort(); + TerminateWithUnhandledException(e.obj()); } catch (...) { // Not a Kotlin exception. oldTerminateHandler(); diff --git a/runtime/src/main/cpp/Exceptions.h b/runtime/src/main/cpp/Exceptions.h index 0ecfb0f3d0f..5b96102e318 100644 --- a/runtime/src/main/cpp/Exceptions.h +++ b/runtime/src/main/cpp/Exceptions.h @@ -31,6 +31,8 @@ OBJ_GETTER(GetStackTraceStrings, KConstRef stackTrace); // Throws arbitrary exception. void ThrowException(KRef exception); +RUNTIME_NORETURN void TerminateWithUnhandledException(KRef exception); + void SetKonanTerminateHandler(); // The functions below are implemented in Kotlin (at package kotlin.native.internal). diff --git a/runtime/src/main/cpp/ObjCExportErrors.mm b/runtime/src/main/cpp/ObjCExportErrors.mm index 94759ed8ac1..1a9968cd8bc 100644 --- a/runtime/src/main/cpp/ObjCExportErrors.mm +++ b/runtime/src/main/cpp/ObjCExportErrors.mm @@ -22,17 +22,41 @@ #import "Exceptions.h" #import "ObjCExport.h" +#import "Porting.h" #import "Runtime.h" #import "Utils.h" extern "C" OBJ_GETTER(Kotlin_Throwable_getMessage, KRef throwable); extern "C" OBJ_GETTER(Kotlin_ObjCExport_getWrappedError, KRef throwable); -extern "C" void Kotlin_ObjCExport_abortIfUnchecked(KRef exception); +extern "C" KBoolean Kotlin_ObjCExport_isUnchecked(KRef exception); + +static void printlnMessage(const char* message) { + konan::consolePrintf("%s\n", message); +} + +static const char* uncheckedExceptionMessage = + "Instances of kotlin.Error, kotlin.RuntimeException and subclasses " + "aren't propagated from Kotlin to Objective-C/Swift."; + +extern "C" RUNTIME_NORETURN void Kotlin_ObjCExport_trapOnUndeclaredException(KRef exception) { + if (Kotlin_ObjCExport_isUnchecked(exception)) { + printlnMessage(uncheckedExceptionMessage); + printlnMessage("Other exceptions can be propagated as NSError if method has or inherits @Throws annotation."); + } else { + printlnMessage("Exceptions are propagated from Kotlin to Objective-C/Swift as NSError " + "only if method has or inherits @Throws annotation"); + } + + TerminateWithUnhandledException(exception); +} static char kotlinExceptionOriginChar; extern "C" void Kotlin_ObjCExport_RethrowExceptionAsNSError(KRef exception, id* outError) { - Kotlin_ObjCExport_abortIfUnchecked(exception); + if (Kotlin_ObjCExport_isUnchecked(exception)) { + printlnMessage(uncheckedExceptionMessage); + TerminateWithUnhandledException(exception); + } if (outError == nullptr) { return; diff --git a/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportUtils.kt b/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportUtils.kt index 50d00b1633a..a665e38600d 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportUtils.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/ObjCExportUtils.kt @@ -281,35 +281,13 @@ class ObjCErrorException( override fun toString(): String = "NSError-based exception: $message" } -private val uncheckedExceptionMessage: String - get() = "Instances of kotlin.Error, kotlin.RuntimeException and subclasses " + - "aren't propagated from Kotlin to Objective-C/Swift." - -private fun Throwable.isUncheckedException(): Boolean = this is kotlin.Error || this is kotlin.RuntimeException - @ExportForCppRuntime -private fun Kotlin_ObjCExport_abortIfUnchecked(exception: Throwable) { - if (exception.isUncheckedException()) { - println(uncheckedExceptionMessage) - ReportUnhandledException(exception) - kotlin.system.exitProcess(1) - } -} +private fun Kotlin_ObjCExport_isUnchecked(exception: Throwable): Boolean = + exception is kotlin.Error || exception is kotlin.RuntimeException -@ExportForCompiler -private fun trapOnUndeclaredException(exception: Throwable) { - if (exception.isUncheckedException()) { - println(uncheckedExceptionMessage) - println("Other exceptions can be propagated as NSError if method has or inherits @Throws annotation.") - } else { - println("Exceptions are propagated from Kotlin to Objective-C/Swift as NSError " + - "only if method has or inherits @Throws annotation") - } - - ReportUnhandledException(exception) - kotlin.system.exitProcess(1) - -} +@PublishedApi +@SymbolName("Kotlin_ObjCExport_trapOnUndeclaredException") +internal external fun trapOnUndeclaredException(exception: Throwable) @ExportForCppRuntime private fun Kotlin_Throwable_getMessage(throwable: Throwable): String? = throwable.message