Make crash with non-converted Kotlin exception debugger-friendly (#2353)

* Use `abort` instead of `exit` to make debugger recognize it as crash
* Terminate from C++ to prevent debugger from showing Kotlin handlers

 #KT-28066 Fixed
This commit is contained in:
SvyatoslavScherbina
2018-11-21 13:34:06 +03:00
committed by GitHub
parent f4cf5e842d
commit 6fe37a00c5
4 changed files with 41 additions and 33 deletions
+8 -4
View File
@@ -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();
+2
View File
@@ -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).
+26 -2
View File
@@ -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;
@@ -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