这是indexloc提供的服务,不要输入任何密码
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Fixes

- Crash in SentryOutOfMemoryScopeObserver (#2557)

## 7.31.4

### Fixes
Expand Down
25 changes: 16 additions & 9 deletions Sources/Sentry/SentryOutOfMemoryScopeObserver.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,22 @@ - (void)switchFileHandle

- (void)store:(NSData *)data
{
[self.fileHandle seekToEndOfFile];
[self.fileHandle writeData:data];
[self.fileHandle writeData:[@"\n" dataUsingEncoding:NSASCIIStringEncoding]];

self.breadcrumbCounter += 1;

if (self.breadcrumbCounter >= self.maxBreadcrumbs) {
[self switchFileHandle];
self.breadcrumbCounter = 0;
unsigned long long fileSize;
@try {
fileSize = [self.fileHandle seekToEndOfFile];

[self.fileHandle writeData:data];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use the newer one with an inout error in addition to wrapping in try, since this one’s deprecated and the error parameter might catch additional info or be used instead of an exception, which would help performance.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but this one only works on iOS 13.0 and above, see https://developer.apple.com/documentation/foundation/nsfilehandle/3172533-writedata

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would create a follow-up issue for using the new APIs, is that fine for you?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that’s fine!

[self.fileHandle writeData:[@"\n" dataUsingEncoding:NSASCIIStringEncoding]];

self.breadcrumbCounter += 1;
} @catch (NSException *exception) {
SENTRY_LOG_ERROR(@"Error while writing data to end file with size (%llu): %@ ", fileSize,
exception.description);
} @finally {
if (self.breadcrumbCounter >= self.maxBreadcrumbs) {
[self switchFileHandle];
self.breadcrumbCounter = 0;
}
}
}

Expand Down
8 changes: 6 additions & 2 deletions Sources/Sentry/include/SentryOutOfMemoryScopeObserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@

NS_ASSUME_NONNULL_BEGIN

/// This scope observer is used by the Out of Memory integration to write breadcrumbs to disk.
/// The overhead is ~0.015 seconds for 1000 breadcrumbs.
/**
* This scope observer is used by the Out of Memory integration to write breadcrumbs to disk.
* The overhead is ~0.015 seconds for 1000 breadcrumbs.
* This class doesn't need to be thread safe as the scope already calls the scope observers in a
* thread safe manner.
*/
@interface SentryOutOfMemoryScopeObserver : NSObject <SentryScopeObserver>
SENTRY_NO_INIT

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import XCTest

class SentryOutOfMemoryScopeObserverTests: XCTestCase {

private static let dsn = TestConstants.dsnAsString(username: "SentryOutOfMemoryScopeObserverTests")

private class Fixture {
let breadcrumb: Breadcrumb
let options: Options
let fileManager: SentryFileManager
let currentDate = TestCurrentDateProvider()
let maxBreadcrumbs = 10

init() {
breadcrumb = TestData.crumb
breadcrumb.data = nil

options = Options()
options.dsn = SentryOutOfMemoryScopeObserverTests.dsn
fileManager = try! SentryFileManager(options: options, andCurrentDateProvider: currentDate)
}

Expand All @@ -20,7 +25,7 @@ class SentryOutOfMemoryScopeObserverTests: XCTestCase {
}

func getSut(fileManager: SentryFileManager) -> SentryOutOfMemoryScopeObserver {
return SentryOutOfMemoryScopeObserver(maxBreadcrumbs: 10, fileManager: fileManager)
return SentryOutOfMemoryScopeObserver(maxBreadcrumbs: maxBreadcrumbs, fileManager: fileManager)
}
}

Expand Down Expand Up @@ -85,7 +90,7 @@ class SentryOutOfMemoryScopeObserverTests: XCTestCase {
XCTAssertEqual(fileTwoLines.count, 1)

// Store 10 more
for _ in 0..<10 {
for _ in 0..<fixture.maxBreadcrumbs {
sut.addSerializedBreadcrumb(breadcrumb)
}

Expand Down Expand Up @@ -118,4 +123,34 @@ class SentryOutOfMemoryScopeObserverTests: XCTestCase {

XCTAssertFalse(FileManager.default.fileExists(atPath: fixture.fileManager.breadcrumbsFilePathTwo))
}

func testWritingToClosedFile() {
let breadcrumb = fixture.breadcrumb.serialize() as! [String: String]

sut.addSerializedBreadcrumb(breadcrumb)

let fileHandle = Dynamic(sut).fileHandle.asObject as! FileHandle
fileHandle.closeFile()

sut.addSerializedBreadcrumb(breadcrumb)

fixture.fileManager.moveBreadcrumbsToPreviousBreadcrumbs()
XCTAssertEqual(1, fixture.fileManager.readPreviousBreadcrumbs().count)
}

func testWritingToFullFileSystem() {
let breadcrumb = fixture.breadcrumb.serialize() as! [String: String]

sut.addSerializedBreadcrumb(breadcrumb)

// "/dev/urandom" simulates a bad file descriptor
let fileHandle = FileHandle(forReadingAtPath: "/dev/urandom")
Dynamic(sut).fileHandle = fileHandle

sut.addSerializedBreadcrumb(breadcrumb)

fixture.fileManager.moveBreadcrumbsToPreviousBreadcrumbs()
XCTAssertEqual(1, fixture.fileManager.readPreviousBreadcrumbs().count)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class SentryCrashScopeObserverTests: XCTestCase {
return jsonPointer!.pointee
}

private func getScopeJson(getField: (SentryCrashScope)-> UnsafeMutablePointer<CChar>?) -> String? {
private func getScopeJson(getField: (SentryCrashScope) -> UnsafeMutablePointer<CChar>?) -> String? {
guard let scopePointer = sentrycrash_scopesync_getScope() else {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/SentryTests/SentryScopeSwiftTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class SentryScopeSwiftTests: XCTestCase {

func testUseSpanForClear() {
fixture.scope.span = fixture.transaction
fixture.scope.useSpan { (span) in
fixture.scope.useSpan { (_) in
self.fixture.scope.span = nil
}
XCTAssertNil(fixture.scope.span)
Expand Down