Browse Source

thread: SDL_CreateThread() shouldn't return before the new thread is set up.

Fixes #15290.

(cherry picked from commit 0756603e6d88d4e453e9dbfba5fea10c15babee6)
Ryan C. Gordon 23 hours ago
parent
commit
2b6bee46b2
2 changed files with 15 additions and 0 deletions
  1. 14 0
      src/thread/SDL_thread.c
  2. 1 0
      src/thread/SDL_thread_c.h

+ 14 - 0
src/thread/SDL_thread.c

@@ -333,6 +333,8 @@ void SDL_RunThread(SDL_Thread *thread)
     // Get the thread id
     thread->threadid = SDL_GetCurrentThreadID();
 
+    SDL_SignalSemaphore(thread->ready_sem);  // the thread is officially ready to run!
+
     // Run the function
     *statusloc = userfunc(userdata);
 
@@ -389,6 +391,13 @@ SDL_Thread *SDL_CreateThreadWithPropertiesRuntime(SDL_PropertiesID props,
         }
     }
 
+    thread->ready_sem = SDL_CreateSemaphore(0);
+    if (!thread->ready_sem) {
+        SDL_free(thread->name);
+        SDL_free(thread);
+        return NULL;
+    }
+
     thread->userfunc = fn;
     thread->userdata = userdata;
     thread->stacksize = stacksize;
@@ -399,11 +408,16 @@ SDL_Thread *SDL_CreateThreadWithPropertiesRuntime(SDL_PropertiesID props,
     if (!SDL_SYS_CreateThread(thread, pfnBeginThread, pfnEndThread)) {
         // Oops, failed.  Gotta free everything
         SDL_SetObjectValid(thread, SDL_OBJECT_TYPE_THREAD, false);
+        SDL_DestroySemaphore(thread->ready_sem);
         SDL_free(thread->name);
         SDL_free(thread);
         thread = NULL;
     }
 
+    SDL_WaitSemaphore(thread->ready_sem);
+    SDL_DestroySemaphore(thread->ready_sem);
+    thread->ready_sem = NULL;
+
     // Everything is running now
     return thread;
 }

+ 1 - 0
src/thread/SDL_thread_c.h

@@ -54,6 +54,7 @@ struct SDL_Thread
     SDL_error errbuf;
     char *name;
     size_t stacksize; // 0 for default, >0 for user-specified stack size.
+    SDL_Semaphore *ready_sem;  // signals when the thread is set up and about to start running.
     int(SDLCALL *userfunc)(void *);
     void *userdata;
     void *data;