From 00283a7267e7c1d4069146fe16f5c14d4e4c08de Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 16 Feb 2016 19:35:54 -0500 Subject: [PATCH] Fix a race condition where PltCloseThread was called before the thread was inserted into the list --- limelight-common/Platform.c | 26 ++++++++++++++++++++++---- limelight-common/PlatformThreads.h | 18 ++++++++++-------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/limelight-common/Platform.c b/limelight-common/Platform.c index 0037e16..7611754 100644 --- a/limelight-common/Platform.c +++ b/limelight-common/Platform.c @@ -40,6 +40,9 @@ void* ThreadProc(void* context) { ctx->thread->next = thread_head; thread_head = ctx->thread; PltUnlockMutex(&thread_list_lock); + + // Signal the event since the thread is now inserted + PltSetEvent(&ctx->thread->insertedEvent); ctx->entry(ctx->context); @@ -164,6 +167,8 @@ void PltCloseThread(PLT_THREAD* thread) { } PltUnlockMutex(&thread_list_lock); + + PltCloseEvent(&thread->insertedEvent); #if defined(LC_WINDOWS) CloseHandle(thread->termRequested); @@ -195,36 +200,49 @@ int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD* thread) { ctx->context = context; ctx->thread = thread; + err = PltCreateEvent(&thread->insertedEvent); + if (err != 0) { + free(ctx); + return err; + } + thread->cancelled = 0; #if defined(LC_WINDOWS) { thread->termRequested = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); if (thread->termRequested == NULL) { + PltCloseEvent(&thread->insertedEvent); free(ctx); return -1; } thread->handle = CreateThread(NULL, 0, ThreadProc, ctx, 0, &thread->tid); if (thread->handle == NULL) { + PltCloseEvent(&thread->insertedEvent); CloseHandle(thread->termRequested); free(ctx); return -1; } - else { - err = 0; - } } #else { err = pthread_create(&thread->thread, NULL, ThreadProc, ctx); if (err != 0) { + PltCloseEvent(&thread->insertedEvent); free(ctx); + return err; } } #endif + + // We shouldn't get this far with an error + LC_ASSERT(err == 0); + + // Wait for the thread to be started and inserted into the active threads list + PltWaitForEvent(&thread->insertedEvent); - return err; + return 0; } int PltCreateEvent(PLT_EVENT* event) { diff --git a/limelight-common/PlatformThreads.h b/limelight-common/PlatformThreads.h index ee01cae..98a6d9d 100644 --- a/limelight-common/PlatformThreads.h +++ b/limelight-common/PlatformThreads.h @@ -6,29 +6,31 @@ typedef void(*ThreadEntry)(void* context); #if defined(LC_WINDOWS) +typedef HANDLE PLT_MUTEX; +typedef HANDLE PLT_EVENT; typedef struct _PLT_THREAD { HANDLE handle; int cancelled; DWORD tid; HANDLE termRequested; + PLT_EVENT insertedEvent; struct _PLT_THREAD* next; } PLT_THREAD; -typedef HANDLE PLT_MUTEX; -typedef HANDLE PLT_EVENT; #elif defined (LC_POSIX) -typedef struct _PLT_THREAD { - pthread_t thread; - int cancelled; - - struct _PLT_THREAD* next; -} PLT_THREAD; typedef pthread_mutex_t PLT_MUTEX; typedef struct _PLT_EVENT { pthread_mutex_t mutex; pthread_cond_t cond; int signalled; } PLT_EVENT; +typedef struct _PLT_THREAD { + pthread_t thread; + int cancelled; + PLT_EVENT insertedEvent; + + struct _PLT_THREAD* next; +} PLT_THREAD; #else #error Unsupported platform #endif