Add more testing for pthread_kill. - Test using `pthread_kill` on yourself. - Test using `pthread_kill` from a background thread to the main thread.
diff --git a/system/lib/libc/raise.c b/system/lib/libc/raise.c index 5e56d5c..b653bf7 100644 --- a/system/lib/libc/raise.c +++ b/system/lib/libc/raise.c
@@ -71,10 +71,10 @@ handler(sig); } } else if (handler != SIG_IGN) { - // Avoid a direct call to the handler, and instead call via JS so we can - // avoid strict signature checking. - // https://github.com/emscripten-core/posixtestsuite/issues/6 - __call_sighandler(handler, sig); + // Avoid a direct call to the handler, and instead call via JS so we can + // avoid strict signature checking. + // https://github.com/emscripten-core/posixtestsuite/issues/6 + __call_sighandler(handler, sig); } } return 0;
diff --git a/system/lib/pthread/pthread_kill.c b/system/lib/pthread/pthread_kill.c index 86e486c..dcaaa00 100644 --- a/system/lib/pthread/pthread_kill.c +++ b/system/lib/pthread/pthread_kill.c
@@ -11,10 +11,8 @@ #include <emscripten_internal.h> #include "pthread_impl.h" -#include "lock.h" -void do_raise(void* arg) { - int sig = (intptr_t)arg; +static void do_raise(int sig) { if (sig == SIGCANCEL) { // For `SIGCANCEL` there is no need to actually call raise to run the // handler function. The calling thread (the one calling `pthread_cancel`) @@ -31,17 +29,17 @@ _emscripten_runtime_keepalive_clear(); return; } - raise((intptr_t)sig); + raise(sig); +} + +static void proxied_do_raise(void* arg) { + do_raise((intptr_t)arg); } int pthread_kill(pthread_t t, int sig) { if (sig < 0 || sig >= _NSIG) { return EINVAL; } - if (t == emscripten_main_runtime_thread_id()) { - if (sig == 0) return 0; // signal == 0 is a no-op. - return ESRCH; - } if (!t || !_emscripten_thread_is_valid(t)) { return ESRCH; } @@ -49,6 +47,10 @@ // The job of pthread_kill is basically to run the (process-wide) signal // handler on the target thread. - emscripten_proxy_async(emscripten_proxy_get_system_queue(), t, do_raise, (void*)(intptr_t)sig); + if (pthread_equal(pthread_self(), t)) { + do_raise(sig); + } else { + emscripten_proxy_async(emscripten_proxy_get_system_queue(), t, proxied_do_raise, (void*)(intptr_t)sig); + } return 0; }
diff --git a/test/pthread/test_pthread_kill.c b/test/pthread/test_pthread_kill.c index 2bc8095..cde9404 100644 --- a/test/pthread/test_pthread_kill.c +++ b/test/pthread/test_pthread_kill.c
@@ -17,14 +17,18 @@ pthread_cond_t started_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t started_lock = PTHREAD_MUTEX_INITIALIZER; -_Atomic bool got_term_signal = false; +_Atomic bool got_sigterm = false; +_Atomic bool got_sigusr1 = false; -pthread_t thr; +pthread_t main_thread; +pthread_t child_thread; void signal_handler(int sig, siginfo_t * info, void * arg) { - printf("signal: %d onthread=%d\n", sig, pthread_self() == thr); + printf("signal: %d onthread=%d\n", sig, pthread_self() == child_thread); if (sig == SIGTERM) { - got_term_signal = true; + got_sigterm = true; + } else if (sig == SIGUSR1) { + got_sigusr1 = true; } } @@ -34,6 +38,7 @@ act.sa_flags = SA_SIGINFO; act.sa_sigaction = signal_handler; sigaction(SIGTERM, &act, NULL); + sigaction(SIGUSR1, &act, NULL); } @@ -46,17 +51,26 @@ pthread_cond_signal(&started_cond); pthread_mutex_unlock(&started_lock); // As long as this thread is running, keep the shared variable latched to nonzero value. - while (!got_term_signal) { + while (!got_sigterm) { sleepms(1); } - printf("got term signal, shutting down thread\n"); - pthread_exit(0); + printf("got term signal, sending signal back to main thread\n"); + pthread_kill(main_thread, SIGUSR1); + return NULL; } int main() { + main_thread = pthread_self(); setup_handler(); - int s = pthread_create(&thr, NULL, thread_start, 0); + printf("tesing pthread_kill with pthread_self\n"); + assert(!got_sigterm); + int s = pthread_kill(pthread_self(), SIGTERM); + assert(got_sigterm); + got_sigterm = false; + assert(s == 0); + + s = pthread_create(&child_thread, NULL, thread_start, 0); assert(s == 0); // Wait until thread kicks in and sets the shared variable. @@ -65,11 +79,15 @@ pthread_mutex_unlock(&started_lock); printf("thread has started, sending SIGTERM\n"); - s = pthread_kill(thr, SIGTERM); + s = pthread_kill(child_thread, SIGTERM); assert(s == 0); printf("SIGTERM sent\n"); - - pthread_join(thr, NULL); + pthread_join(child_thread, NULL); + printf("joined child_thread\n"); + while (!got_sigusr1) { + sleepms(1); + } + printf("got SIGUSR1. all done.\n"); return 0; }
diff --git a/test/pthread/test_pthread_kill.out b/test/pthread/test_pthread_kill.out index 63ee2d8..9c0d30a 100644 --- a/test/pthread/test_pthread_kill.out +++ b/test/pthread/test_pthread_kill.out
@@ -1,4 +1,9 @@ +tesing pthread_kill with pthread_self +signal: 15 onthread=0 thread has started, sending SIGTERM SIGTERM sent signal: 15 onthread=1 -got term signal, shutting down thread +got term signal, sending signal back to main thread +joined child_thread +signal: 10 onthread=0 +got SIGUSR1. all done.