Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### Fixes

- Fix misleading duplicate SDK detection message: "same binary" → "same address space" (#8710)
- Fix a race caused by mutating `URLSessionTask.currentRequest` during trace header propagation (#8650)

## 9.25.0
Expand Down
2 changes: 1 addition & 1 deletion Sources/Swift/Tools/LoadValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ import MachO
continue
}
if name.contains(self.targetClassName) {
var message = ["❌ Sentry SDK was loaded multiple times in the same binary ❌"]
var message = ["❌ Sentry SDK was loaded multiple times in the same address space ❌"]
message.append("⚠️ This can cause undefined behavior, crashes, or duplicate reporting.")
message.append("Ensure the SDK is linked only once, found `\(self.targetClassName)` class in image path: \(imageName)")
SentrySDKLog.error(message.joined(separator: "\n"))
Expand Down
8 changes: 5 additions & 3 deletions Tests/DuplicatedSDKTest/Unit Tests/Unit_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ final class TestLog: XCTestCase {
stopCapturingOutput()
super.tearDown()
}


private let loadedMultipleTimesMessage = "Sentry SDK was loaded multiple times in the same address space"

func testDuplicatedLoadMessageOnSDKInit() throws {
let expectation = XCTestExpectation(description: "Wait for duplicated SDK load message")

Expand All @@ -38,7 +40,7 @@ final class TestLog: XCTestCase {
let checkQueue = DispatchQueue(label: "message.check")
checkQueue.async {
while self.isCapturing {
if self.capturedOutput.contains("Sentry SDK was loaded multiple times in the same binary") {
if self.capturedOutput.contains(self.loadedMultipleTimesMessage) {
expectation.fulfill()
break
}
Expand All @@ -49,7 +51,7 @@ final class TestLog: XCTestCase {
// This expectation is fulfilled immediately on a mac, but takes way longer on CI
wait(for: [expectation], timeout: 600.0)

XCTAssertTrue(capturedOutput.contains("Sentry SDK was loaded multiple times in the same binary"))
XCTAssertTrue(capturedOutput.contains(loadedMultipleTimesMessage))
}

private func startCapturingOutput() {
Expand Down
20 changes: 11 additions & 9 deletions Tests/SentryTests/Swift/Core/Tools/LoadValidatorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ class LoadValidatorTests: XCTestCase {
private var dispatchQueueWrapper: TestSentryDispatchQueueWrapper!
private var defaultImageAddress: UInt64 = 0x1000
private var defaultImageSize: UInt64 = 0x20


private let loadedMultipleTimesMessage = "❌ Sentry SDK was loaded multiple times in the same address space ❌"

// MARK: - Setup and Teardown

override func setUp() {
Expand Down Expand Up @@ -58,7 +60,7 @@ class LoadValidatorTests: XCTestCase {
// Assert
XCTAssertFalse(validationResult, "Validation should return false for system libraries")
XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a system library")
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") })
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) })
XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0)
}

Expand Down Expand Up @@ -86,7 +88,7 @@ class LoadValidatorTests: XCTestCase {
// Assert
XCTAssertFalse(validationResult, "Validation should return false for simulator libraries")
XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a simulator library")
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") })
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) })
XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0)
}

Expand Down Expand Up @@ -114,7 +116,7 @@ class LoadValidatorTests: XCTestCase {
// Assert
XCTAssertFalse(validationResult, "Validation should return false for cryptex simulator libraries")
XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a cryptex simulator library")
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") })
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) })
XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0)
}

Expand Down Expand Up @@ -142,7 +144,7 @@ class LoadValidatorTests: XCTestCase {
// Assert
XCTAssertFalse(validationResult, "Validation should return false for system libraries")
XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a simulator library")
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") })
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) })
XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0)
}

Expand Down Expand Up @@ -170,7 +172,7 @@ class LoadValidatorTests: XCTestCase {
// Assert
XCTAssertFalse(validationResult, "Validation should return false")
XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary")
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") })
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) })
XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1)
}

Expand Down Expand Up @@ -201,7 +203,7 @@ class LoadValidatorTests: XCTestCase {
// Assert
XCTAssertTrue(validationResult, "Validation should skip for app binary")
XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary")
XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times in the same binary ❌") })
XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) })
XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("⚠️ This can cause undefined behavior, crashes, or duplicate reporting.") })
XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("Ensure the SDK is linked only once, found `SentryDependencyContainerSwiftHelper` class in image path: \(imageName)") })
XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1)
Expand Down Expand Up @@ -234,7 +236,7 @@ class LoadValidatorTests: XCTestCase {
// Assert
XCTAssertTrue(validationResult, "Validation should return true for app")
XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary")
XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times in the same binary ❌") })
XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) })
XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("⚠️ This can cause undefined behavior, crashes, or duplicate reporting.") })
XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("Ensure the SDK is linked only once, found `SentryDependencyContainerSwiftHelper` class in image path: \(imageName)") })
XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1)
Expand Down Expand Up @@ -271,7 +273,7 @@ class LoadValidatorTests: XCTestCase {
// Assert
XCTAssertFalse(validationResult, "Validation should skip for sentry framework")
XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should not be called for an app binary")
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") })
XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) })
XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1)
}
}
Loading