Skip to content

Commit

Permalink
fix: memory issue crash happening on CloudModeProcessor
Browse files Browse the repository at this point in the history
* fix: finalize the sql statement to release the resources and add autorelease pool logic

* chore: add exception catching method to avoid crashing

* chore: update catch block to release the thread lock

Co-authored-by: Abhishek Pandey <[email protected]>

---------

Co-authored-by: Abhishek Pandey <[email protected]>
  • Loading branch information
SKannaniOS and 1abhishekpandey authored Oct 7, 2024
1 parent e909634 commit ddc2d05
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 54 deletions.
86 changes: 46 additions & 40 deletions Sources/Classes/RSCloudModeManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,50 +38,56 @@ - (void) startCloudModeProcessor {
RSCloudModeManager *strongSelf = weakSelf;
[RSLogger logDebug:@"RSCloudModeManager: CloudModeProcessor: Starting the Cloud Mode Processor"];
int sleepCount = 0;

while (YES) {
[strongSelf->lock lock];
RSNetworkResponse* response = nil;
[strongSelf->dbPersistentManager clearOldEventsWithThreshold: strongSelf->config.dbCountThreshold];
[RSLogger logDebug:@"RSCloudModeManager: CloudModeProcessor: Fetching events to flush to server"];
RSDBMessage* dbMessage = [strongSelf->dbPersistentManager fetchEventsFromDB:(strongSelf->config.flushQueueSize) ForMode:CLOUDMODE];
if ((dbMessage.messages.count >= strongSelf->config.flushQueueSize) || (dbMessage.messages.count > 0 && (sleepCount >= strongSelf->config.sleepTimeout))) {
NSString* payload = [RSCloudModeManager getPayloadFromMessages:dbMessage];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Payload: %@", payload]];
[RSLogger logInfo:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: EventCount: %lu", (unsigned long)dbMessage.messageIds.count]];
[RSMetricsReporter report:SDKMETRICS_CM_EVENT forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_MESSAGES} andValue:(float)dbMessage.messages.count];
if (payload != nil) {
response = [strongSelf->networkManager sendNetworkRequest:payload toEndpoint:BATCH_ENDPOINT withRequestMethod:POST];
if (response.state == NETWORK_SUCCESS) {
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Updating status as CLOUDMODEPROCESSING DONE for events (%@)",[RSUtils getCSVStringFromArray:dbMessage.messageIds]]];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_SUCCESS forMetricType:COUNT withProperties:nil andValue:(float)dbMessage.messages.count];
[strongSelf->dbPersistentManager updateEventsWithIds:dbMessage.messageIds withStatus:CLOUD_MODE_PROCESSING_DONE];
[strongSelf->dbPersistentManager clearProcessedEventsFromDB];
sleepCount = 0;
[self->backOff reset];
@try {
[strongSelf->lock lock];
RSNetworkResponse* response = nil;
[strongSelf->dbPersistentManager clearOldEventsWithThreshold: strongSelf->config.dbCountThreshold];
[RSLogger logDebug:@"RSCloudModeManager: CloudModeProcessor: Fetching events to flush to server"];
RSDBMessage* dbMessage = [strongSelf->dbPersistentManager fetchEventsFromDB:(strongSelf->config.flushQueueSize) ForMode:CLOUDMODE];
if ((dbMessage.messages.count >= strongSelf->config.flushQueueSize) || (dbMessage.messages.count > 0 && (sleepCount >= strongSelf->config.sleepTimeout))) {
NSString* payload = [RSCloudModeManager getPayloadFromMessages:dbMessage];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Payload: %@", payload]];
[RSLogger logInfo:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: EventCount: %lu", (unsigned long)dbMessage.messageIds.count]];
[RSMetricsReporter report:SDKMETRICS_CM_EVENT forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_MESSAGES} andValue:(float)dbMessage.messages.count];
if (payload != nil) {
response = [strongSelf->networkManager sendNetworkRequest:payload toEndpoint:BATCH_ENDPOINT withRequestMethod:POST];
if (response.state == NETWORK_SUCCESS) {
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Updating status as CLOUDMODEPROCESSING DONE for events (%@)",[RSUtils getCSVStringFromArray:dbMessage.messageIds]]];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_SUCCESS forMetricType:COUNT withProperties:nil andValue:(float)dbMessage.messages.count];
[strongSelf->dbPersistentManager updateEventsWithIds:dbMessage.messageIds withStatus:CLOUD_MODE_PROCESSING_DONE];
[strongSelf->dbPersistentManager clearProcessedEventsFromDB];
sleepCount = 0;
[self->backOff reset];
}
}
}
[strongSelf->lock unlock];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: cloudModeSleepCount: %d", sleepCount]];
sleepCount += 1;

if(response == nil) {
sleep(1);
} else if (response.state == WRONG_WRITE_KEY) {
[RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Wrong WriteKey. Aborting the Cloud Mode Processor"];
break;
} else if (response.state == INVALID_URL) {
[RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Invalid Data Plane URL. Aborting the Cloud Mode Processor"];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_ABORT forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_DATA_PLANE_URL_INVALID} andValue:1];
break;
} else if (response.state == NETWORK_ERROR) {
int delay = [self->backOff nextDelay];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: %@", [RSUtils secondsToString:delay]]];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_RETRY forMetricType:COUNT withProperties:nil andValue:1];
sleep(delay);
} else { // To handle the status code RESOURCE_NOT_FOUND(404) & BAD_REQUEST(400)
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: 1s"]];
sleep(1);
}
}
[strongSelf->lock unlock];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: cloudModeSleepCount: %d", sleepCount]];
sleepCount += 1;

if(response == nil) {
sleep(1);
} else if (response.state == WRONG_WRITE_KEY) {
[RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Wrong WriteKey. Aborting the Cloud Mode Processor"];
break;
} else if (response.state == INVALID_URL) {
[RSLogger logError:@"RSCloudModeManager: CloudModeProcessor: Invalid Data Plane URL. Aborting the Cloud Mode Processor"];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_ABORT forMetricType:COUNT withProperties:@{SDKMETRICS_TYPE: SDKMETRICS_DATA_PLANE_URL_INVALID} andValue:1];
break;
} else if (response.state == NETWORK_ERROR) {
int delay = [self->backOff nextDelay];
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: %@", [RSUtils secondsToString:delay]]];
[RSMetricsReporter report:SDKMETRICS_CM_ATTEMPT_RETRY forMetricType:COUNT withProperties:nil andValue:1];
sleep(delay);
} else { // To handle the status code RESOURCE_NOT_FOUND(404) & BAD_REQUEST(400)
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSCloudModeManager: CloudModeProcessor: Retrying in: 1s"]];
@catch (NSException *exception) {
[strongSelf->lock unlock];
[RSLogger logError:[NSString stringWithFormat:@"RSCloudModeManager: CloudModeProcessor: Failed to flush current batch, reason: %@", exception.reason]];
sleep(1);
}
}
Expand Down
37 changes: 23 additions & 14 deletions Sources/Classes/RSDBPersistentManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -491,30 +491,39 @@ -(RSDBMessage*) fetchAllEventsFromDBForMode:(MODES) mode {

- (RSDBMessage *) getEventsFromDB :(NSString*) querySQLString {
[RSLogger logDebug:[[NSString alloc] initWithFormat:@"RSDBPersistentManager: getEventsFromDB: fetchEventSql: %@", querySQLString]];

const char* querySQL = [querySQLString UTF8String];
NSMutableArray<NSString *> *messageIds = [[NSMutableArray alloc] init];
NSMutableArray<NSString *> *messages = [[NSMutableArray alloc] init];
NSMutableArray<NSNumber *>* statusList = [[NSMutableArray alloc] init];
NSMutableArray<NSNumber *>* dmProcessedList = [[NSMutableArray alloc] init];
NSMutableArray<NSString *> *messageIds = [NSMutableArray array];
NSMutableArray<NSString *> *messages = [NSMutableArray array];
NSMutableArray<NSNumber *> *statusList = [NSMutableArray array];
NSMutableArray<NSNumber *> *dmProcessedList = [NSMutableArray array];

@synchronized (self) {
void *queryStmt = nil;
sqlite3_stmt *queryStmt = nil;
if ([database prepare_v2:querySQL nBytes:-1 ppStmt:&queryStmt pzTail:NULL] == SQLITE_OK) {
[RSLogger logDebug:@"RSDBPersistentManager: getEventsFromDB: Successfully fetched events from DB"];
while ([database step:queryStmt] == SQLITE_ROW) {
int messageId = [database column_int:queryStmt i:0];
const unsigned char* queryResultCol1 = [database column_text:queryStmt i:1];
NSString *message = [[NSString alloc] initWithUTF8String:(char *)queryResultCol1];
int status = [database column_int:queryStmt i:3];
int dmProcessed = [database column_int:queryStmt i:4];
[messageIds addObject:[[NSString alloc] initWithFormat:@"%d", messageId]];
[messages addObject:message];
[statusList addObject:[NSNumber numberWithInt:status]];
[dmProcessedList addObject:[NSNumber numberWithInt:dmProcessed]];
@autoreleasepool {
int messageId = [database column_int:queryStmt i:0];
const unsigned char* queryResultCol1 = [database column_text:queryStmt i:1];
NSString *message = [[NSString alloc] initWithUTF8String:(char *)queryResultCol1];
int status = [database column_int:queryStmt i:3];
int dmProcessed = [database column_int:queryStmt i:4];

[messageIds addObject:[[NSString alloc] initWithFormat:@"%d", messageId]];
[messages addObject:message];
[statusList addObject:[NSNumber numberWithInt:status]];
[dmProcessedList addObject:[NSNumber numberWithInt:dmProcessed]];
}
}
} else {
[RSLogger logError:@"RSDBPersistentManager: getEventsFromDB: Failed to fetch events from DB"];
}

// Finalize the SQL statement to free resources
if (queryStmt != nil) {
[database finalize:queryStmt];
}
}

RSDBMessage *dbMessage = [[RSDBMessage alloc] init];
Expand Down

0 comments on commit ddc2d05

Please sign in to comment.