Skip to content

Commit ca90a4b

Browse files
authored
Fix error reporting from pthread_join (#15417)
pthread_join should check for thread validity and for detached state before it checks for joining self (i.e. deadlock). Needed for (split out from) #13006.
1 parent 95d5695 commit ca90a4b

File tree

2 files changed

+35
-16
lines changed

2 files changed

+35
-16
lines changed

src/library_pthread.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -878,25 +878,24 @@ var LibraryPThread = {
878878
err('pthread_join attempted on a null thread pointer!');
879879
return {{{ cDefine('ESRCH') }}};
880880
}
881-
if (ENVIRONMENT_IS_PTHREAD && _pthread_self() == thread) {
882-
err('PThread ' + thread + ' is attempting to join to itself!');
883-
return {{{ cDefine('EDEADLK') }}};
884-
}
885-
else if (!ENVIRONMENT_IS_PTHREAD && _emscripten_main_browser_thread_id() == thread) {
886-
err('Main thread ' + thread + ' is attempting to join to itself!');
887-
return {{{ cDefine('EDEADLK') }}};
888-
}
889881
var self = {{{ makeGetValue('thread', C_STRUCTS.pthread.self, 'i32') }}};
890882
if (self !== thread) {
891883
err('pthread_join attempted on thread ' + thread + ', which does not point to a valid thread, or does not exist anymore!');
892884
return {{{ cDefine('ESRCH') }}};
893885
}
894-
895886
var detached = Atomics.load(HEAPU32, (thread + {{{ C_STRUCTS.pthread.detached }}} ) >> 2);
896887
if (detached) {
897888
err('Attempted to join thread ' + thread + ', which was already detached!');
898889
return {{{ cDefine('EINVAL') }}}; // The thread is already detached, can no longer join it!
899890
}
891+
if (ENVIRONMENT_IS_PTHREAD && _pthread_self() == thread) {
892+
err('PThread ' + thread + ' is attempting to join to itself!');
893+
return {{{ cDefine('EDEADLK') }}};
894+
}
895+
else if (!ENVIRONMENT_IS_PTHREAD && _emscripten_main_browser_thread_id() == thread) {
896+
err('Main thread ' + thread + ' is attempting to join to itself!');
897+
return {{{ cDefine('EDEADLK') }}};
898+
}
900899

901900
#if ASSERTIONS || IN_TEST_HARNESS || !MINIMAL_RUNTIME || !ALLOW_BLOCKING_ON_MAIN_THREAD
902901
if (block) {

tests/other/test_pthread_self_join_detach.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,41 @@
22
#include <errno.h>
33
#include <pthread.h>
44
#include <stdio.h>
5+
#include <string.h>
56

67
#include <emscripten/threading.h>
78

89
int main() {
10+
/*
11+
* When running in PROXY_TO_PTHREAD mode the main thread
12+
* is already detached
13+
*/
14+
int is_detached = !emscripten_is_main_browser_thread();
915
pthread_t self = pthread_self();
1016

11-
/* Join the calling thread. This should fail with EDEADLK. */
12-
assert(pthread_join(self, NULL) == EDEADLK);
17+
/*
18+
* Attempts to join the current thread will either generate
19+
* EDEADLK or EINVAL depending on whether has already been
20+
* detached
21+
*/
22+
int ret = pthread_join(self, NULL);
23+
if (is_detached) {
24+
assert(ret == EINVAL);
25+
} else {
26+
assert(ret == EDEADLK);
27+
}
1328

14-
/* We should be able to detach the main thread,
15-
* but not the proxied main thread (as that one
16-
* is already detached).
29+
/*
30+
* Attempts to detach the main thread will either succeed
31+
* or cause EINVAL if its already been detached.
1732
*/
18-
int ret = emscripten_is_main_browser_thread() ? 0 : EINVAL;
19-
assert(pthread_detach(self) == ret);
33+
ret = pthread_detach(self);
34+
printf("pthread_detach(self) -> %s\n", strerror(ret));
35+
if (is_detached) {
36+
assert(ret == EINVAL);
37+
} else {
38+
assert(ret == 0);
39+
}
2040

2141
puts("passed");
2242

0 commit comments

Comments
 (0)