Skip to content

Commit 51c60c1

Browse files
authored
Fix Semaphore Timeout (#409)
• When getting the current notification state in iOS 10 +, our SDK was using a semaphore to do this synchronously. • However, the SDK was waiting on the semaphore with unlimited timeout, so there was the potential to block the thread indefinitely. • Adds a 100 millisecond timeout to ensure this call never results in a blocked thread
1 parent 4402343 commit 51c60c1

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

iOS_SDK/OneSignalSDK/Source/OneSignalNotificationSettingsIOS10.m

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,14 @@
3434

3535
#import "OneSignalHelper.h"
3636

37-
@implementation OneSignalNotificationSettingsIOS10 {
37+
@interface OneSignalNotificationSettingsIOS10 ()
3838

3939
// Used as both an optimization and to prevent queue deadlocks.
40-
// This doesn't seem to be required for the latter at this time. (2.4.3)
41-
BOOL useCachedStatus;
42-
}
40+
@property (atomic) BOOL useCachedStatus;
41+
42+
@end
43+
44+
@implementation OneSignalNotificationSettingsIOS10
4345

4446
// Used to run all calls to getNotificationSettingsWithCompletionHandler sequentially
4547
// This prevents any possible deadlocks due to race condiditions.
@@ -54,7 +56,7 @@ - (instancetype)init {
5456
}
5557

5658
- (void)getNotificationPermissionState:(void (^)(OSPermissionState *subcscriptionStatus))completionHandler {
57-
if (useCachedStatus) {
59+
if (self.useCachedStatus) {
5860
completionHandler(OneSignal.currentPermissionState);
5961
return;
6062
}
@@ -68,18 +70,32 @@ - (void)getNotificationPermissionState:(void (^)(OSPermissionState *subcscriptio
6870
status.accepted = settings.authorizationStatus == UNAuthorizationStatusAuthorized;
6971
status.answeredPrompt = settings.authorizationStatus != UNAuthorizationStatusNotDetermined;
7072
status.notificationTypes = (settings.badgeSetting == UNNotificationSettingEnabled ? 1 : 0)
71-
+ (settings.soundSetting == UNNotificationSettingEnabled ? 2 : 0)
72-
+ (settings.alertSetting == UNNotificationSettingEnabled ? 4 : 0)
73-
+ (settings.lockScreenSetting == UNNotificationSettingEnabled ? 8 : 0);
74-
useCachedStatus = true;
73+
+ (settings.soundSetting == UNNotificationSettingEnabled ? 2 : 0)
74+
+ (settings.alertSetting == UNNotificationSettingEnabled ? 4 : 0)
75+
+ (settings.lockScreenSetting == UNNotificationSettingEnabled ? 8 : 0);
76+
self.useCachedStatus = true;
7577
completionHandler(status);
76-
useCachedStatus = false;
78+
self.useCachedStatus = false;
7779
}];
7880
});
7981
}
8082

83+
// used only in cases where UNUserNotificationCenter getNotificationSettingsWith...
84+
// callback does not get executed in a timely fashion. Rather than returning nil,
85+
- (OSPermissionState *)defaultPermissionState {
86+
if (OneSignal.currentPermissionState != nil) {
87+
return OneSignal.currentPermissionState;
88+
}
89+
90+
OSPermissionState *defaultState = [OSPermissionState new];
91+
92+
defaultState.notificationTypes = 0;
93+
94+
return defaultState;
95+
}
96+
8197
- (OSPermissionState*)getNotificationPermissionState {
82-
if (useCachedStatus)
98+
if (self.useCachedStatus)
8399
return OneSignal.currentPermissionState;
84100

85101
__block OSPermissionState* returnStatus = OneSignal.currentPermissionState;
@@ -90,9 +106,10 @@ - (OSPermissionState*)getNotificationPermissionState {
90106
dispatch_semaphore_signal(semaphore);
91107
}];
92108
});
93-
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
94109

95-
return returnStatus;
110+
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(100 * NSEC_PER_MSEC)));
111+
112+
return returnStatus ?: self.defaultPermissionState;
96113
}
97114

98115
- (int)getNotificationTypes {

0 commit comments

Comments
 (0)