Browse Source

Make sure SDL subsystems are initialized before starting threads

Sam Lantinga 9 months ago
parent
commit
bd041b4831
3 changed files with 38 additions and 16 deletions
  1. 34 15
      src/SDL.c
  2. 3 0
      src/SDL_internal.h
  3. 1 1
      src/thread/SDL_thread.c

+ 34 - 15
src/SDL.c

@@ -113,6 +113,7 @@ static SDL_bool SDL_MainIsReady = SDL_FALSE;
 #else
 static SDL_bool SDL_MainIsReady = SDL_TRUE;
 #endif
+static SDL_bool SDL_main_thread_initialized = SDL_FALSE;
 static SDL_bool SDL_bInMainQuit = SDL_FALSE;
 static Uint8 SDL_SubsystemRefCount[32];
 
@@ -182,21 +183,45 @@ void SDL_SetMainReady(void)
     SDL_MainIsReady = SDL_TRUE;
 }
 
-int SDL_InitSubSystem(Uint32 flags)
+/* Initialize all the subsystems that require initialization before threads start */
+void SDL_InitMainThread(void)
 {
-    Uint32 flags_initialized = 0;
-
-    if (!SDL_MainIsReady) {
-        return SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?");
+    if (SDL_main_thread_initialized) {
+        return;
     }
 
     SDL_InitTLSData();
+    SDL_InitTicks();
     SDL_InitLog();
     SDL_InitProperties();
     SDL_GetGlobalProperties();
 
-    /* Clear the error message */
-    SDL_ClearError();
+    SDL_main_thread_initialized = SDL_TRUE;
+}
+
+static void SDL_QuitMainThread(void)
+{
+    if (!SDL_main_thread_initialized) {
+        return;
+    }
+
+    SDL_QuitProperties();
+    SDL_QuitLog();
+    SDL_QuitTicks();
+    SDL_QuitTLSData();
+
+    SDL_main_thread_initialized = SDL_FALSE;
+}
+
+int SDL_InitSubSystem(Uint32 flags)
+{
+    Uint32 flags_initialized = 0;
+
+    if (!SDL_MainIsReady) {
+        return SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?");
+    }
+
+    SDL_InitMainThread();
 
 #ifdef SDL_USE_LIBDBUS
     SDL_DBus_Init();
@@ -210,8 +235,6 @@ int SDL_InitSubSystem(Uint32 flags)
     }
 #endif
 
-    SDL_InitTicks();
-
     /* Initialize the event subsystem */
     if (flags & SDL_INIT_EVENTS) {
         if (SDL_ShouldInitSubsystem(SDL_INIT_EVENTS)) {
@@ -542,8 +565,6 @@ void SDL_Quit(void)
 #endif
     SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
 
-    SDL_QuitTicks();
-
 #ifdef SDL_USE_LIBDBUS
     SDL_DBus_Quit();
 #endif
@@ -556,9 +577,6 @@ void SDL_Quit(void)
 
     SDL_QuitCPUInfo();
 
-    SDL_QuitProperties();
-    SDL_QuitLog();
-
     /* Now that every subsystem has been quit, we reset the subsystem refcount
      * and the list of initialized subsystems.
      */
@@ -566,7 +584,8 @@ void SDL_Quit(void)
 
     SDL_FlushEventMemory(0);
     SDL_FreeEnvironmentMemory();
-    SDL_QuitTLSData();
+
+    SDL_QuitMainThread();
 
     SDL_bInMainQuit = SDL_FALSE;
 }

+ 3 - 0
src/SDL_internal.h

@@ -289,6 +289,9 @@
 extern "C" {
 #endif
 
+/* Do any initialization that needs to happen before threads are started */
+extern void SDL_InitMainThread(void);
+
 extern int SDLCALL SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS);
 extern int SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS);
 extern SDL_bool SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS);

+ 1 - 1
src/thread/SDL_thread.c

@@ -371,7 +371,7 @@ SDL_Thread *SDL_CreateThreadWithPropertiesRuntime(SDL_PropertiesID props,
         return NULL;
     }
 
-    SDL_InitTLSData();
+    SDL_InitMainThread();
 
     SDL_Thread *thread = (SDL_Thread *)SDL_calloc(1, sizeof(*thread));
     if (!thread) {