1 #pragma once
2
3 #include <pthread.h>
4 #include <signal.h>
5
6 // Signal handler that does nothing but indicates receipt
signal_handler(int signo)7 static void signal_handler(int signo) {
8 /* Nothing to do */
9 }
10
11 // Macro to set up SIG signal handler to do nothing
12 #define SETUP_SIG_HANDLER(sig) \
13 do { \
14 struct sigaction sa; \
15 sa.sa_handler = signal_handler; \
16 sa.sa_flags = 0; \
17 sigemptyset(&sa.sa_mask); \
18 sigaction(sig, &sa, NULL); \
19 } while (0)
20
21 // Macros for signal handling
22 #define ENABLE_SIGNAL(sig) \
23 do { \
24 SETUP_SIG_HANDLER(sig); /* Ensure SIG is handled by empty_signal_handler */ \
25 sigset_t set; \
26 sigemptyset(&set); \
27 sigaddset(&set, sig); \
28 pthread_sigmask(SIG_UNBLOCK, &set, NULL); \
29 } while (0)
30
31 #define DISABLE_SIGNAL(sig) \
32 do { \
33 sigset_t set; \
34 sigemptyset(&set); \
35 sigaddset(&set, sig); \
36 pthread_sigmask(SIG_BLOCK, &set, NULL); \
37 } while (0)
38
39 // Macros to simulate pthread_setcancelstate and pthread_cancel
40 #define PTHREAD_CANCEL_ENABLE 1
41 #define PTHREAD_CANCEL_DISABLE 0
42
43 #define pthread_setcancelstate(state, oldstate) \
44 do { \
45 static __thread int thread_cancel_state = PTHREAD_CANCEL_ENABLE; \
46 if (oldstate != NULL) { \
47 *(int*)oldstate = thread_cancel_state; \
48 } \
49 if (state == PTHREAD_CANCEL_ENABLE) { \
50 thread_cancel_state = PTHREAD_CANCEL_ENABLE; \
51 ENABLE_SIGNAL(SIGUSR1); \
52 } else if (state == PTHREAD_CANCEL_DISABLE) { \
53 thread_cancel_state = PTHREAD_CANCEL_DISABLE; \
54 DISABLE_SIGNAL(SIGUSR1); \
55 } \
56 } while (0)
57
58 #define pthread_cancel(thread) \
59 do { \
60 pthread_kill(thread, SIGUSR1); \
61 } while (0)
62