|
| 1 | +// Copyright 2015 The Emscripten Authors. All rights reserved. |
| 2 | +// Emscripten is available under two separate licenses, the MIT license and the |
| 3 | +// University of Illinois/NCSA Open Source License. Both these licenses can be |
| 4 | +// found in the LICENSE file. |
| 5 | + |
| 6 | +#include <pthread.h> |
| 7 | +#include <sys/types.h> |
| 8 | +#include <stdio.h> |
| 9 | +#include <stdlib.h> |
| 10 | +#include <stdbool.h> |
| 11 | +#include <assert.h> |
| 12 | +#include <unistd.h> |
| 13 | +#include <errno.h> |
| 14 | +#include <emscripten/console.h> |
| 15 | + |
| 16 | +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; |
| 17 | +_Atomic long res = 43; |
| 18 | +_Atomic int started = false; |
| 19 | + |
| 20 | +static void cleanup_handler(void *arg) |
| 21 | +{ |
| 22 | + long a = (long)arg; |
| 23 | + emscripten_outf("Called clean-up handler with arg %ld", a); |
| 24 | + res -= a; |
| 25 | +} |
| 26 | + |
| 27 | +static void *thread_start(void *arg) { |
| 28 | + // Setup thread for async cancelation only |
| 29 | + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); |
| 30 | + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); |
| 31 | + |
| 32 | + pthread_cleanup_push(cleanup_handler, (void*)42); |
| 33 | + |
| 34 | + emscripten_out("Thread started!"); |
| 35 | + |
| 36 | + // Signal the main thread that are started |
| 37 | + started = true; |
| 38 | + |
| 39 | + // This mutex is locked by the main thread so this call should never return. |
| 40 | + // pthread_mutex_lock is not a cancellation point so deferred cancellation |
| 41 | + // won't work here, async cancelation should. |
| 42 | + pthread_mutex_lock(&mutex); |
| 43 | + |
| 44 | + assert(false && "pthread_mutex_lock returned!"); |
| 45 | + pthread_cleanup_pop(0); |
| 46 | +} |
| 47 | + |
| 48 | +int main() { |
| 49 | + pthread_mutex_lock(&mutex); |
| 50 | + |
| 51 | + emscripten_out("Starting thread.."); |
| 52 | + pthread_t thr; |
| 53 | + int s = pthread_create(&thr, NULL, thread_start, (void*)0); |
| 54 | + assert(s == 0); |
| 55 | + // Busy wait until thread is started |
| 56 | + while (!started) { |
| 57 | + sched_yield(); |
| 58 | + } |
| 59 | + |
| 60 | + emscripten_out("Canceling thread.."); |
| 61 | + s = pthread_cancel(thr); |
| 62 | + assert(s == 0); |
| 63 | + // Busy wait until thread cancel handler has been run |
| 64 | + while (res != 1) { |
| 65 | + sched_yield(); |
| 66 | + } |
| 67 | + |
| 68 | + emscripten_out("Joining thread.."); |
| 69 | + s = pthread_join(thr, NULL); |
| 70 | + assert(s == 0); |
| 71 | + emscripten_out("done"); |
| 72 | + return 0; |
| 73 | +} |
0 commit comments