forked from emscripten-core/emscripten
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixing thread exit and thread cancellation (emscripten-core#12985)
This patch fixes thread cancellation/exit method and also unifies why how thread structures are updated when thread is canceled or exits. Following problems are addressed: 1. heap-use-after-free on std::thread emscripten-core#12985 Function `cleanupThread()` from `src/library_pthread.js` unconditionally set `pthread.self` member of pthread structure to 0. Problem was that `cleanupThread()` function might be called after that pthread structure has been deleted. To fix this problem, setting `pthread.self` field is now guarded by check if thread data hasn't been already freed. 2. pthread_cond_wait/2-3 test hang - Disabling recursive thread cancellation. - Allowing __timedwait_cp to be true cancellation point as _cp suffix suggests 3. pthread_getschedparam/1-3 test hangs sometimes: In pthread_barrier_wait adding check if lock is held by main thread and waiting on futex in small slices of time there, to check if there is some work to do on behalf of Worker Threads. Signed-off-by: Adam Bujalski <[email protected]>
Showing
7 changed files
with
137 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright 2021 The Emscripten Authors. All rights reserved. | ||
// Emscripten is available under two separate licenses, the MIT license and the | ||
// University of Illinois/NCSA Open Source License. Both these licenses can be | ||
// found in the LICENSE file. | ||
|
||
#include <pthread.h> | ||
#include <sys/types.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <assert.h> | ||
#include <unistd.h> | ||
#include <errno.h> | ||
#include <emscripten.h> | ||
#include <emscripten/threading.h> | ||
|
||
pthread_barrier_t barrier; | ||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | ||
pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; | ||
|
||
int th_cancelled = 0; | ||
|
||
volatile int res = 43; | ||
|
||
static void cleanup_handler(void *arg) { | ||
emscripten_log(EM_LOG_CONSOLE, "Called clean-up handler with arg %p", arg); | ||
int a = reinterpret_cast<int>(arg); | ||
res -= a; | ||
|
||
pthread_mutex_unlock(&mutex); | ||
pthread_barrier_wait(&barrier); | ||
} | ||
|
||
static void *thread_start(void *arg) { | ||
pthread_cleanup_push(cleanup_handler, (void*)42); | ||
emscripten_log(EM_LOG_CONSOLE, "Thread started!"); | ||
pthread_mutex_lock(&mutex); | ||
pthread_barrier_wait(&barrier); | ||
|
||
int ret = 0; | ||
do { | ||
emscripten_log(EM_LOG_CONSOLE, "Waiting on conditional variable"); | ||
ret = pthread_cond_wait(&condvar, &mutex); | ||
} while (ret == 0 && th_cancelled == 0); | ||
|
||
if (ret != 0) { | ||
emscripten_log(EM_LOG_CONSOLE, "Cond wait failed ret: %d", ret); | ||
} | ||
|
||
res = 1000; // Shouldn't ever reach here. | ||
pthread_cleanup_pop(0); | ||
|
||
pthread_mutex_unlock(&mutex); | ||
pthread_barrier_wait(&barrier); | ||
return NULL; | ||
} | ||
|
||
int main() { | ||
if (!emscripten_has_threading_support()) { | ||
printf("Skipped: Threading is not supported.\n"); | ||
return 1; | ||
} | ||
|
||
pthread_barrier_init(&barrier, nullptr, 2); | ||
|
||
pthread_t thr; | ||
int s = pthread_create(&thr, NULL, thread_start, (void*)0); | ||
assert(s == 0); | ||
emscripten_log(EM_LOG_CONSOLE, "Thread created"); | ||
|
||
pthread_barrier_wait(&barrier); | ||
|
||
// Lock mutex to ensure that thread is waiting | ||
pthread_mutex_lock(&mutex); | ||
|
||
emscripten_log(EM_LOG_CONSOLE, "Canceling thread.."); | ||
s = pthread_cancel(thr); | ||
assert(s == 0); | ||
th_cancelled = 1; | ||
pthread_mutex_unlock(&mutex); | ||
|
||
emscripten_log(EM_LOG_CONSOLE, "Main thread waitnig for side-thread"); | ||
pthread_barrier_wait(&barrier); | ||
pthread_barrier_destroy(&barrier); | ||
|
||
emscripten_log(EM_LOG_CONSOLE, "Test finished result: %d", res); | ||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters