Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions NSExceptionKtCrashlytics/CrashlyticsNSExceptionKtReporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ private class CrashlyticsNSExceptionKtReporter: NSExceptionKtReporter {

private let crashlytics: Crashlytics
private let causedByStrategy: CausedByStrategy
private static var isReporting = false
private static let lock = NSLock()

public var requiresMergedException: Bool { causedByStrategy == .append }

Expand All @@ -33,6 +35,20 @@ private class CrashlyticsNSExceptionKtReporter: NSExceptionKtReporter {
}

public func reportException(_ exceptions: [NSException]) {
Self.lock.lock()
guard !Self.isReporting else {
Self.lock.unlock()
return
}
Self.isReporting = true
Self.lock.unlock()

defer {
Self.lock.lock()
Self.isReporting = false
Self.lock.unlock()
}

if causedByStrategy == .logNonFatal {
for exception in exceptions.reversed().dropLast() {
crashlytics.record(exceptionModel: .init(exception))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ public fun addReporter(
* of the [causes][Throwable.cause] will be appended, else causes are ignored.
*/
@OptIn(UnsafeNumber::class, ExperimentalForeignApi::class)
internal fun Throwable.asNSException(appendCausedBy: Boolean = false): NSException {
internal fun Throwable.asNSException(appendCausedBy: Boolean = false): NSException = try {
val returnAddresses = getFilteredStackTraceAddresses().let { addresses ->
if (!appendCausedBy) return@let addresses
addresses.toMutableList().apply {
for (cause in causes) {
addAll(cause.getFilteredStackTraceAddresses(true, addresses))
}
}
}.map {
NSNumber(unsignedInteger = it.convert<NSUInteger>())
}
return ThrowableNSException(name, getReason(appendCausedBy), returnAddresses)
}.map { NSNumber(unsignedInteger = it.convert<NSUInteger>()) }
ThrowableNSException(name, getReason(appendCausedBy), returnAddresses)
} catch (e: Throwable) {
ThrowableNSException(name, message, emptyList())
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.rickclephas.kmp.nsexceptionkt.core

import kotlin.experimental.ExperimentalNativeApi
import kotlin.concurrent.AtomicReference
import kotlin.concurrent.AtomicInt

/**
* Wraps the unhandled exception hook such that the provided [hook] is invoked
Expand All @@ -13,9 +14,14 @@ import kotlin.concurrent.AtomicReference
@OptIn(ExperimentalNativeApi::class)
internal fun wrapUnhandledExceptionHook(hook: (Throwable) -> Unit) {
val prevHook = AtomicReference<ReportUnhandledExceptionHook?>(null)
val isReporting = AtomicInt(0)
val wrappedHook: ReportUnhandledExceptionHook = {
hook(it)
prevHook.value?.invoke(it)
if (isReporting.compareAndSet(0, 1)) {
try {
hook(it)
} catch (e: Throwable) {}
prevHook.value?.invoke(it)
}
terminateWithUnhandledException(it)
}
prevHook.value = setUnhandledExceptionHook(wrappedHook)
Expand Down