From 353a5c230729eec260f3f54c0fc3f70cf1a3ca1a Mon Sep 17 00:00:00 2001 From: Jesus Rojas Date: Wed, 20 May 2026 14:12:28 -0600 Subject: [PATCH 1/6] [Crashlytics] Fix deadlock in user logging on reentrant queue access --- Crashlytics/Crashlytics/Components/FIRCLSContext.m | 10 ++++++++++ Crashlytics/Crashlytics/Components/FIRCLSGlobals.h | 2 ++ Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/Crashlytics/Crashlytics/Components/FIRCLSContext.m index 8d64268460f..a17e240bd78 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSContext.m +++ b/Crashlytics/Crashlytics/Components/FIRCLSContext.m @@ -245,6 +245,8 @@ void FIRCLSContextBaseInit(void) { NSString* exceptionQueueName = [sdkBundleID stringByAppendingString:@".exception"]; _firclsLoggingQueue = dispatch_queue_create([loggingQueueName UTF8String], DISPATCH_QUEUE_SERIAL); + dispatch_queue_set_specific(_firclsLoggingQueue, &_firclsLoggingQueue, &_firclsLoggingQueue, + NULL); _firclsBinaryImageQueue = dispatch_queue_create([binaryImagesQueueName UTF8String], DISPATCH_QUEUE_SERIAL); _firclsExceptionQueue = @@ -437,3 +439,11 @@ bool FIRCLSContextRecordMetadata(NSString* rootPath, const FIRCLSContextInitData return true; } + +void FIRCLSExecuteOnLoggingQueue(void (^block)(void)) { + if (dispatch_get_specific(&_firclsLoggingQueue) != NULL) { + block(); + } else { + dispatch_sync(_firclsLoggingQueue, block); + } +} diff --git a/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h b/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h index 10173ed4eaf..5c5d55ee230 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h +++ b/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h @@ -25,4 +25,6 @@ extern dispatch_queue_t _firclsExceptionQueue; #define FIRCLSGetBinaryImageQueue() (_firclsBinaryImageQueue) #define FIRCLSGetExceptionQueue() (_firclsExceptionQueue) +void FIRCLSExecuteOnLoggingQueue(void (^block)(void)); + __END_DECLS diff --git a/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m b/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m index 19a169f881a..4218e747baa 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m +++ b/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m @@ -283,7 +283,7 @@ void FIRCLSUserLoggingRecordKeysAndValues(NSDictionary *keysAndValues, } } - dispatch_sync(FIRCLSGetLoggingQueue(), ^{ + FIRCLSExecuteOnLoggingQueue(^{ FIRCLSUserLoggingWriteKeysAndValues(sanitizedKeysAndValues, storage, counter, containsNullValue); }); @@ -541,7 +541,7 @@ void FIRCLSUserLoggingWriteAndCheckABFiles(FIRCLSUserLoggingABStorage *storage, } } - dispatch_sync(FIRCLSGetLoggingQueue(), ^{ + FIRCLSExecuteOnLoggingQueue(^{ FIRCLSFile file; if (!FIRCLSFileInitWithPath(&file, *activePath, true)) { From 1e1ff7256ad849fa091a20dadbb4dc7d2afdfe72 Mon Sep 17 00:00:00 2001 From: Jesus Rojas Date: Wed, 20 May 2026 14:20:01 -0600 Subject: [PATCH 2/6] add defensive checks to safe queue helper --- Crashlytics/Crashlytics/Components/FIRCLSContext.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/Crashlytics/Crashlytics/Components/FIRCLSContext.m index a17e240bd78..2f8f5f68fc0 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSContext.m +++ b/Crashlytics/Crashlytics/Components/FIRCLSContext.m @@ -441,9 +441,13 @@ bool FIRCLSContextRecordMetadata(NSString* rootPath, const FIRCLSContextInitData } void FIRCLSExecuteOnLoggingQueue(void (^block)(void)) { + if (!block) { + return; + } + if (dispatch_get_specific(&_firclsLoggingQueue) != NULL) { block(); - } else { + } else if (_firclsLoggingQueue) { dispatch_sync(_firclsLoggingQueue, block); } } From f3b3cd68f9e67bb270636a0be42256767f6847a5 Mon Sep 17 00:00:00 2001 From: Jesus Rojas Date: Wed, 20 May 2026 14:34:43 -0600 Subject: [PATCH 3/6] check logging queue before setting specific data --- Crashlytics/Crashlytics/Components/FIRCLSContext.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/Crashlytics/Crashlytics/Components/FIRCLSContext.m index 2f8f5f68fc0..588d9ad99de 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSContext.m +++ b/Crashlytics/Crashlytics/Components/FIRCLSContext.m @@ -245,8 +245,10 @@ void FIRCLSContextBaseInit(void) { NSString* exceptionQueueName = [sdkBundleID stringByAppendingString:@".exception"]; _firclsLoggingQueue = dispatch_queue_create([loggingQueueName UTF8String], DISPATCH_QUEUE_SERIAL); - dispatch_queue_set_specific(_firclsLoggingQueue, &_firclsLoggingQueue, &_firclsLoggingQueue, - NULL); + if (_firclsLoggingQueue) { + dispatch_queue_set_specific(_firclsLoggingQueue, &_firclsLoggingQueue, &_firclsLoggingQueue, + NULL); + } _firclsBinaryImageQueue = dispatch_queue_create([binaryImagesQueueName UTF8String], DISPATCH_QUEUE_SERIAL); _firclsExceptionQueue = From e0cb2075f39b1370e173e18fa0d14d54771e4cfc Mon Sep 17 00:00:00 2001 From: Jesus Rojas Date: Wed, 20 May 2026 14:53:57 -0600 Subject: [PATCH 4/6] execute block directly if logging queue is NULL --- Crashlytics/Crashlytics/Components/FIRCLSContext.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/Crashlytics/Crashlytics/Components/FIRCLSContext.m index 588d9ad99de..d27ac777ab6 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSContext.m +++ b/Crashlytics/Crashlytics/Components/FIRCLSContext.m @@ -447,9 +447,9 @@ void FIRCLSExecuteOnLoggingQueue(void (^block)(void)) { return; } - if (dispatch_get_specific(&_firclsLoggingQueue) != NULL) { + if (dispatch_get_specific(&_firclsLoggingQueue) != NULL || !_firclsLoggingQueue) { block(); - } else if (_firclsLoggingQueue) { + } else { dispatch_sync(_firclsLoggingQueue, block); } } From d97313afbf7bed69618b385a4d9daa27cf52a2ab Mon Sep 17 00:00:00 2001 From: Jesus Rojas Date: Wed, 20 May 2026 15:01:59 -0600 Subject: [PATCH 5/6] reorder logging queue guard for readability --- Crashlytics/Crashlytics/Components/FIRCLSContext.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/Crashlytics/Crashlytics/Components/FIRCLSContext.m index d27ac777ab6..83559d83d17 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSContext.m +++ b/Crashlytics/Crashlytics/Components/FIRCLSContext.m @@ -447,7 +447,7 @@ void FIRCLSExecuteOnLoggingQueue(void (^block)(void)) { return; } - if (dispatch_get_specific(&_firclsLoggingQueue) != NULL || !_firclsLoggingQueue) { + if (!_firclsLoggingQueue || dispatch_get_specific(&_firclsLoggingQueue) != NULL) { block(); } else { dispatch_sync(_firclsLoggingQueue, block); From e485ee681bdcaf9b63b7ada39ff44a271759e5f9 Mon Sep 17 00:00:00 2001 From: Jesus Rojas Date: Wed, 20 May 2026 15:43:36 -0600 Subject: [PATCH 6/6] log warning when logging queue is NULL --- Crashlytics/Crashlytics/Components/FIRCLSContext.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/Crashlytics/Crashlytics/Components/FIRCLSContext.m index 83559d83d17..327367cc97f 100644 --- a/Crashlytics/Crashlytics/Components/FIRCLSContext.m +++ b/Crashlytics/Crashlytics/Components/FIRCLSContext.m @@ -447,7 +447,11 @@ void FIRCLSExecuteOnLoggingQueue(void (^block)(void)) { return; } - if (!_firclsLoggingQueue || dispatch_get_specific(&_firclsLoggingQueue) != NULL) { + if (!_firclsLoggingQueue) { + FIRCLSSDKLogWarn( + "FIRCLSExecuteOnLoggingQueue invoked with NULL logging queue; running block inline.\n"); + block(); + } else if (dispatch_get_specific(&_firclsLoggingQueue) != NULL) { block(); } else { dispatch_sync(_firclsLoggingQueue, block);