Skip to content

Commit 1b5b3d2

Browse files
author
AR Abdul Azeez
committed
Fix login race condition and JWT FAIL_UNAUTHORIZED blocking callers
1. Make non-suspend login()/logout() block the caller via runBlocking instead of fire-and-forget (Thread/suspendifyOnIO), restoring pre-5.3 behavior so tags target the correct user after each login. 2. Wake enqueueAndWait waiters on FAIL_UNAUTHORIZED and FAIL_PAUSE_OPREPO before re-queuing operations. Re-queued items use waiter=null so future retries don't reference stale waiters. This prevents loginSuspend from hanging forever when a JWT is invalid or the op repo pauses. Fixes SDK-4338 Made-with: Cursor
1 parent 258c8e6 commit 1b5b3d2

2 files changed

Lines changed: 20 additions & 14 deletions

File tree

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationRepo.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,11 @@ internal class OperationRepo(
288288
if (externalId != null) {
289289
_jwtTokenStore.invalidateJwt(externalId)
290290
Logging.warn("Operation execution failed with 401 Unauthorized, JWT invalidated for user: $externalId. Operations re-queued.")
291+
ops.forEach { it.waiter?.wake(false) }
291292
synchronized(queue) {
292-
ops.reversed().forEach { queue.add(0, it) }
293+
ops.reversed().forEach {
294+
queue.add(0, OperationQueueItem(it.operation, waiter = null, bucket = it.bucket, retries = it.retries))
295+
}
293296
}
294297
dispatchJwtInvalidatedToApp(externalId)
295298
} else {
@@ -331,9 +334,12 @@ internal class OperationRepo(
331334
Logging.error("Operation execution failed with eventual retry, pausing the operation repo: $operations")
332335
// keep the failed operation and pause the operation repo from executing
333336
paused = true
337+
ops.forEach { it.waiter?.wake(false) }
334338
// add back all operations to the front of the queue to be re-executed.
335339
synchronized(queue) {
336-
ops.reversed().forEach { queue.add(0, it) }
340+
ops.reversed().forEach {
341+
queue.add(0, OperationQueueItem(it.operation, waiter = null, bucket = it.bucket, retries = it.retries))
342+
}
337343
}
338344
}
339345
}

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/internal/OneSignalImp.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -384,16 +384,16 @@ internal class OneSignalImp(
384384

385385
if (isBackgroundThreadingEnabled) {
386386
waitForInit(operationName = "login")
387-
suspendifyOnIO { loginHelper.login(externalId, jwtBearerToken) }
387+
runBlocking(runtimeIoDispatcher) {
388+
loginHelper.login(externalId, jwtBearerToken)
389+
}
388390
} else {
389391
if (!isInitialized) {
390392
throw IllegalStateException("Must call 'initWithContext' before 'login'")
391393
}
392-
Thread {
393-
runBlocking(runtimeIoDispatcher) {
394-
loginHelper.login(externalId, jwtBearerToken)
395-
}
396-
}.start()
394+
runBlocking(runtimeIoDispatcher) {
395+
loginHelper.login(externalId, jwtBearerToken)
396+
}
397397
}
398398
}
399399

@@ -402,16 +402,16 @@ internal class OneSignalImp(
402402

403403
if (isBackgroundThreadingEnabled) {
404404
waitForInit(operationName = "logout")
405-
suspendifyOnIO { logoutHelper.logout() }
405+
runBlocking(runtimeIoDispatcher) {
406+
logoutHelper.logout()
407+
}
406408
} else {
407409
if (!isInitialized) {
408410
throw IllegalStateException("Must call 'initWithContext' before 'logout'")
409411
}
410-
Thread {
411-
runBlocking(runtimeIoDispatcher) {
412-
logoutHelper.logout()
413-
}
414-
}.start()
412+
runBlocking(runtimeIoDispatcher) {
413+
logoutHelper.logout()
414+
}
415415
}
416416
}
417417

0 commit comments

Comments
 (0)