From 48e213b4cddea928b824cc46d285df98d904f6e0 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 26 Sep 2024 18:08:58 -0700
Subject: [PATCH] Fixed SDL_ShouldQuit() returning false during status
transitions
We should wait for the state to stabilize before SDL_ShouldQuit() returns.
For example:
Thread A initializes and increments a use refcount
Thread B skips initializing and increments the use refcount
Thread B starts cleaning up and checks the use refcount
Thread A starts cleaning up, returns because SDL_ShouldQuit() returns false (not initialized), not touching the use refcount
Thread B returns because the use refcount isn't zero
Now we have the state where the refcount is greater than one and both thread A and B have attempted to cleanup.
With this change:
Thread A initializes and increments a use refcount
Thread B skips initializing and increments the use refcount
Thread B starts cleaning up and decrements and checks the use refcount
Thread A starts cleaning up, waits for thread B
Thread B returns because the use refcount isn't zero
Thread A continues and decrements and checks the use refcount, and finishes cleaning up because it has reached 0.
---
src/thread/SDL_thread.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c
index d2b914524c8f1..177dc2102cee6 100644
--- a/src/thread/SDL_thread.c
+++ b/src/thread/SDL_thread.c
@@ -533,9 +533,14 @@ bool SDL_ShouldInit(SDL_InitState *state)
bool SDL_ShouldQuit(SDL_InitState *state)
{
- if (SDL_CompareAndSwapAtomicInt(&state->status, SDL_INIT_STATUS_INITIALIZED, SDL_INIT_STATUS_UNINITIALIZING)) {
- state->thread = SDL_GetCurrentThreadID();
- return true;
+ while (SDL_GetAtomicInt(&state->status) != SDL_INIT_STATUS_UNINITIALIZED) {
+ if (SDL_CompareAndSwapAtomicInt(&state->status, SDL_INIT_STATUS_INITIALIZED, SDL_INIT_STATUS_UNINITIALIZING)) {
+ state->thread = SDL_GetCurrentThreadID();
+ return true;
+ }
+
+ // Wait for the other thread to complete transition
+ SDL_Delay(1);
}
return false;
}