Fix a race condition where PltCloseThread was called before the thread was inserted into the list

This commit is contained in:
Cameron Gutman 2016-02-16 19:35:54 -05:00
parent ca870694ba
commit 00283a7267
2 changed files with 32 additions and 12 deletions

View File

@ -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) {

View File

@ -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