Skip to content
Draft
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 Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,9 @@
9286059729A5098900F96038 /* SentryGeo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9286059629A5098900F96038 /* SentryGeo.m */; };
9286059929A50BAB00F96038 /* SentryGeoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9286059829A50BAA00F96038 /* SentryGeoTests.swift */; };
928BED2B2E16977A00B4D398 /* SentryLogBatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 928BED2A2E16977A00B4D398 /* SentryLogBatcherTests.swift */; };
92B472832EF1AD7A00DD2891 /* SentryBatchBufferC.c in Sources */ = {isa = PBXBuildFile; fileRef = 92B472822EF1AD7A00DD2891 /* SentryBatchBufferC.c */; };
92B472842EF1AD7A00DD2891 /* SentryBatchBufferC.h in Headers */ = {isa = PBXBuildFile; fileRef = 92B472812EF1AD7A00DD2891 /* SentryBatchBufferC.h */; };
92B4728B2EF1ADA000DD2891 /* CrashSafeBatchBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B4728A2EF1ADA000DD2891 /* CrashSafeBatchBuffer.swift */; };
92B6BDA92E05B8F600D538B3 /* SentryLogLevelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B6BDA82E05B8F000D538B3 /* SentryLogLevelTests.swift */; };
92B6BDAD2E05B9FB00D538B3 /* SentryLogTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B6BDAC2E05B9F700D538B3 /* SentryLogTests.swift */; };
92D957732E05A44600E20E66 /* SentryAsyncLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 92D957722E05A44600E20E66 /* SentryAsyncLog.m */; };
Expand Down Expand Up @@ -821,6 +824,7 @@
D4D7AA762EEADF4B00E28DFB /* InMemoryBatchBufferTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D7AA752EEADF4800E28DFB /* InMemoryBatchBufferTests.swift */; };
D4D7AA782EEAE30F00E28DFB /* BatcherScopeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D7AA772EEAE30B00E28DFB /* BatcherScopeTests.swift */; };
D4DDC0F42EE8572F00F321F6 /* BatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DDC0F32EE8572F00F321F6 /* BatcherTests.swift */; };
92B4728D2EF1ADB000DD2891 /* CrashSafeBatchBufferTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B4728C2EF1ADB000DD2891 /* CrashSafeBatchBufferTests.swift */; };
D4DEE6592E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */; };
D4E3F35D2D4A864600F79E2B /* SentryNSDictionarySanitizeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42E48582D48FC8F00D251BC /* SentryNSDictionarySanitizeTests.swift */; };
D4E3F35E2D4A877300F79E2B /* SentryNSDictionarySanitize+Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = D41909942D490006002B83D0 /* SentryNSDictionarySanitize+Tests.m */; };
Expand Down Expand Up @@ -2077,6 +2081,9 @@
9286059629A5098900F96038 /* SentryGeo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryGeo.m; sourceTree = "<group>"; };
9286059829A50BAA00F96038 /* SentryGeoTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryGeoTests.swift; sourceTree = "<group>"; };
928BED2A2E16977A00B4D398 /* SentryLogBatcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogBatcherTests.swift; sourceTree = "<group>"; };
92B472812EF1AD7A00DD2891 /* SentryBatchBufferC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryBatchBufferC.h; sourceTree = "<group>"; };
92B472822EF1AD7A00DD2891 /* SentryBatchBufferC.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SentryBatchBufferC.c; sourceTree = "<group>"; };
92B4728A2EF1ADA000DD2891 /* CrashSafeBatchBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashSafeBatchBuffer.swift; sourceTree = "<group>"; };
92B6BDA82E05B8F000D538B3 /* SentryLogLevelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogLevelTests.swift; sourceTree = "<group>"; };
92B6BDAC2E05B9F700D538B3 /* SentryLogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogTests.swift; sourceTree = "<group>"; };
92D957722E05A44600E20E66 /* SentryAsyncLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAsyncLog.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2194,6 +2201,7 @@
D4D7AA752EEADF4800E28DFB /* InMemoryBatchBufferTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InMemoryBatchBufferTests.swift; sourceTree = "<group>"; };
D4D7AA772EEAE30B00E28DFB /* BatcherScopeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatcherScopeTests.swift; sourceTree = "<group>"; };
D4DDC0F32EE8572F00F321F6 /* BatcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatcherTests.swift; sourceTree = "<group>"; };
92B4728C2EF1ADB000DD2891 /* CrashSafeBatchBufferTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashSafeBatchBufferTests.swift; sourceTree = "<group>"; };
D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryProfileTimeseriesTests.m; sourceTree = "<group>"; };
D4E942042E9D1CF300DB7521 /* TestSessionReplayEnvironmentChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSessionReplayEnvironmentChecker.swift; sourceTree = "<group>"; };
D4E9420B2E9D1D7600DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSessionReplayEnvironmentCheckerTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3250,6 +3258,8 @@
63FE700520DA4C1000CDBAE8 /* Tools */ = {
isa = PBXGroup;
children = (
92B472812EF1AD7A00DD2891 /* SentryBatchBufferC.h */,
92B472822EF1AD7A00DD2891 /* SentryBatchBufferC.c */,
63FE702E20DA4C1000CDBAE8 /* SentryCrashNSErrorUtil.h */,
63FE700E20DA4C1000CDBAE8 /* SentryCrashNSErrorUtil.m */,
63FE703E20DA4C1000CDBAE8 /* SentryCrashCPU_Apple.h */,
Expand Down Expand Up @@ -4465,6 +4475,7 @@
D4D7AA692EEAD89300E28DFB /* BatcherItem.swift */,
D4D7AA6A2EEAD89300E28DFB /* BatcherScope.swift */,
D4D7AA6B2EEAD89300E28DFB /* BatchBuffer.swift */,
92B4728A2EF1ADA000DD2891 /* CrashSafeBatchBuffer.swift */,
D4D7AA6C2EEAD89300E28DFB /* InMemoryBatchBuffer.swift */,
);
path = Batcher;
Expand All @@ -4476,6 +4487,7 @@
D4D7AA772EEAE30B00E28DFB /* BatcherScopeTests.swift */,
D4DDC0F32EE8572F00F321F6 /* BatcherTests.swift */,
D4D7AA752EEADF4800E28DFB /* InMemoryBatchBufferTests.swift */,
92B4728C2EF1ADB000DD2891 /* CrashSafeBatchBufferTests.swift */,
);
path = Batcher;
sourceTree = "<group>";
Expand Down Expand Up @@ -5231,6 +5243,7 @@
84AF45A629A7FFA500FBB177 /* SentryProfiledTracerConcurrency.h in Headers */,
8EAE980B261E9F530073B6B3 /* SentryPerformanceTracker.h in Headers */,
F48F75732E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h in Headers */,
92B472842EF1AD7A00DD2891 /* SentryBatchBufferC.h in Headers */,
63FE718520DA4C1100CDBAE8 /* SentryCrashC.h in Headers */,
8EA1ED0D2669028C00E62B98 /* SentryUIViewControllerSwizzling.h in Headers */,
D820CDB82BB1895F00BA339D /* SentrySessionReplayIntegration.h in Headers */,
Expand Down Expand Up @@ -5852,6 +5865,7 @@
92D957732E05A44600E20E66 /* SentryAsyncLog.m in Sources */,
7B08A3472924CF9C0059603A /* SentryMetricKitIntegration.m in Sources */,
623FD9022D3FA5E000803EDA /* SentryFrameCodable.swift in Sources */,
92B472832EF1AD7A00DD2891 /* SentryBatchBufferC.c in Sources */,
62BDDD122D51FD540024CCD1 /* SentryThreadCodable.swift in Sources */,
7B63459B280EB9E200CFA05A /* SentryUIEventTrackingIntegration.m in Sources */,
15E0A8ED240F2CB000F044E3 /* SentrySerialization.m in Sources */,
Expand Down Expand Up @@ -5940,6 +5954,7 @@
843FB3232D0CD04D00558F18 /* SentryUserAccess.m in Sources */,
63FE716720DA4C1100CDBAE8 /* SentryCrashCPU.c in Sources */,
63FE717320DA4C1100CDBAE8 /* SentryCrashC.c in Sources */,
92B4728B2EF1ADA000DD2891 /* CrashSafeBatchBuffer.swift in Sources */,
D4D7AA6E2EEAD89300E28DFB /* Batcher.swift in Sources */,
D4D7AA6F2EEAD89300E28DFB /* BatchBuffer.swift in Sources */,
D4D7AA702EEAD89300E28DFB /* BatcherItem.swift in Sources */,
Expand Down Expand Up @@ -6345,6 +6360,7 @@
7B6C5ED6264E62CA0010D138 /* SentryTransactionTests.swift in Sources */,
D81FDF12280EA1060045E0E4 /* SentryScreenshotSourceTests.swift in Sources */,
D4DDC0F42EE8572F00F321F6 /* BatcherTests.swift in Sources */,
92B4728D2EF1ADB000DD2891 /* CrashSafeBatchBufferTests.swift in Sources */,
D8019910286B089000C277F0 /* SentryCrashReportSinkTests.swift in Sources */,
D885266427739D01001269FC /* SentryFileIOTrackingIntegrationTests.swift in Sources */,
7BBD18992449DE9D00427C76 /* TestRateLimits.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions Sources/Sentry/include/SentryPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import "NSLocale+Sentry.h"
#import "SentryANRStoppedResultInternal.h"
#import "SentryANRTrackerInternalDelegate.h"
#import "SentryBatchBufferC.h"
#import "SentryBinaryImageCacheCallbacks.h"
#import "SentryClient+Private.h"
#import "SentryConcurrentRateLimitsDictionary.h"
Expand Down
168 changes: 168 additions & 0 deletions Sources/SentryCrash/Recording/Tools/SentryBatchBufferC.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
//
// sentry_batch_buffer.c
//
// Buffer wrapper for managing memory buffers.
//

#include "SentryBatchBufferC.h"
#include <stdlib.h>
#include <string.h>

bool
sentry_batch_buffer_init(SentryBatchBufferC *buffer, size_t data_capacity, size_t items_capacity)
{
if (buffer == NULL) {
return false;
}

buffer->data = NULL;
buffer->data_capacity = 0;
buffer->data_size = 0;
buffer->item_offsets = NULL;
buffer->item_sizes = NULL;
buffer->items_capacity = 0;
buffer->item_count = 0;

if (data_capacity == 0 || items_capacity == 0) {
return true;
}

buffer->data = (char *)malloc(data_capacity);
if (buffer->data == NULL) {
return false;
}
buffer->data_capacity = data_capacity;

buffer->item_offsets = (size_t *)malloc(items_capacity * sizeof(size_t));
if (buffer->item_offsets == NULL) {
free(buffer->data);
buffer->data = NULL;
return false;
}

buffer->item_sizes = (size_t *)malloc(items_capacity * sizeof(size_t));
if (buffer->item_sizes == NULL) {
free(buffer->item_offsets);
free(buffer->data);
buffer->item_offsets = NULL;
buffer->data = NULL;
return false;
}

buffer->items_capacity = items_capacity;

return true;
}

void
sentry_batch_buffer_destroy(SentryBatchBufferC *buffer)
{
if (buffer == NULL) {
return;
}

if (buffer->data != NULL) {
free(buffer->data);
buffer->data = NULL;
}

if (buffer->item_offsets != NULL) {
free(buffer->item_offsets);
buffer->item_offsets = NULL;
}

if (buffer->item_sizes != NULL) {
free(buffer->item_sizes);
buffer->item_sizes = NULL;
}

buffer->data_capacity = 0;
buffer->data_size = 0;
buffer->items_capacity = 0;
buffer->item_count = 0;
}

bool
sentry_batch_buffer_add_item(SentryBatchBufferC *buffer, const char *data, size_t length)
{
if (buffer == NULL || data == NULL) {
return false;
}

if (length == 0) {
return true;
}

if (buffer->item_count >= buffer->items_capacity) {
return false;
}

if (buffer->data_size + length > buffer->data_capacity) {
return false;
}

buffer->item_offsets[buffer->item_count] = buffer->data_size;
buffer->item_sizes[buffer->item_count] = length;

memcpy(buffer->data + buffer->data_size, data, length);
buffer->data_size += length;

buffer->item_count++;
return true;
}

const char *
sentry_batch_buffer_get_item(const SentryBatchBufferC *buffer, size_t index, size_t *size_out)
{
if (buffer == NULL) {
return NULL;
}

if (index >= buffer->item_count) {
return NULL;
}

if (size_out != NULL) {
*size_out = buffer->item_sizes[index];
}

return buffer->data + buffer->item_offsets[index];
}

const char *
sentry_batch_buffer_get_data(const SentryBatchBufferC *buffer)
{
if (buffer == NULL || buffer->data == NULL || buffer->data_size == 0) {
return NULL;
}
return buffer->data;
}

size_t
sentry_batch_buffer_get_data_size(const SentryBatchBufferC *buffer)
{
if (buffer == NULL) {
return 0;
}
return buffer->data_size;
}

void
sentry_batch_buffer_clear(SentryBatchBufferC *buffer)
{
if (buffer == NULL) {
return;
}

buffer->data_size = 0;
buffer->item_count = 0;
}

size_t
sentry_batch_buffer_get_item_count(const SentryBatchBufferC *buffer)
{
if (buffer == NULL) {
return 0;
}
return buffer->item_count;
}
50 changes: 50 additions & 0 deletions Sources/SentryCrash/Recording/Tools/SentryBatchBufferC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// sentry_batch_buffer.h
//
// Buffer wrapper for managing memory buffers.
//

#ifndef HDR_SENTRY_BATCH_BUFFER_H
#define HDR_SENTRY_BATCH_BUFFER_H

#include <stdbool.h>
#include <stddef.h>

typedef struct {
char *data;
size_t data_capacity;
size_t data_size;

size_t *item_offsets;
size_t *item_sizes;

size_t items_capacity;
size_t item_count;
} SentryBatchBufferC;

/** @return true if initialization was successful, false otherwise.
*
* @note This function is NOT async-signal-safe because it calls malloc().
*/
bool sentry_batch_buffer_init(
SentryBatchBufferC *buffer, size_t data_capacity, size_t items_capacity);

void sentry_batch_buffer_destroy(SentryBatchBufferC *buffer);

/** @return true if the item was successfully added, false if buffer is full. */
bool sentry_batch_buffer_add_item(SentryBatchBufferC *buffer, const char *data, size_t length);

/** @return A pointer to the item's data, or NULL if index is invalid. */
const char *sentry_batch_buffer_get_item(
const SentryBatchBufferC *buffer, size_t index, size_t *size_out);

/** @return A pointer to the data buffer, or NULL if the buffer is empty. */
const char *sentry_batch_buffer_get_data(const SentryBatchBufferC *buffer);

size_t sentry_batch_buffer_get_data_size(const SentryBatchBufferC *buffer);

void sentry_batch_buffer_clear(SentryBatchBufferC *buffer);

size_t sentry_batch_buffer_get_item_count(const SentryBatchBufferC *buffer);

#endif // HDR_SENTRY_BATCH_BUFFER_H
4 changes: 4 additions & 0 deletions Sources/Swift/Tools/Batcher/BatchBuffer.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
enum BatchBufferError: Error {
case bufferFull
}

protocol BatchBuffer<Item> {
associatedtype Item

Expand Down
64 changes: 64 additions & 0 deletions Sources/Swift/Tools/Batcher/CrashSafeBatchBuffer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
@_implementationOnly import _SentryPrivate
import Foundation

/// Errors that can occur when using `CrashSafeBatchBuffer`.
enum CrashSafeBatchBufferError: Error {
case initializationFailed
}

/// A wrapper around the `SentryBatchBufferC` C API.
final class CrashSafeBatchBuffer {
private var buffer: SentryBatchBufferC

init(dataCapacity: Int, itemsCapacity: Int) throws {
var cBuffer = SentryBatchBufferC()
guard sentry_batch_buffer_init(&cBuffer, dataCapacity, itemsCapacity) else {
throw CrashSafeBatchBufferError.initializationFailed
}
self.buffer = cBuffer
}

deinit {
sentry_batch_buffer_destroy(&buffer)
}

/// Adds raw data to the buffer.
/// - Parameter data: The data to add
/// - Returns: `true` if the item was successfully added, `false` if the buffer is full
func addItem(_ data: Data) -> Bool {
guard !data.isEmpty else {
return true
}
return data.withUnsafeBytes { bytes in
guard let baseAddress = bytes.baseAddress else {
return false
}
return sentry_batch_buffer_add_item(&buffer, baseAddress.assumingMemoryBound(to: CChar.self), data.count)
}
}

func clear() {
sentry_batch_buffer_clear(&buffer)
}

var itemCount: Int {
return Int(sentry_batch_buffer_get_item_count(&buffer))
}

var dataSize: Int {
return Int(sentry_batch_buffer_get_data_size(&buffer))
}

func getAllItems() -> [Data] {
var items: [Data] = []
let count = itemCount
for i in 0..<count {
var itemSize: size_t = 0
guard let itemData = sentry_batch_buffer_get_item(&buffer, i, &itemSize) else {
continue
}
items.append(Data(bytes: itemData, count: Int(itemSize)))
}
return items
}
}
Loading
Loading