1 /* $OpenBSD: errno.c,v 1.3 2021/06/23 22:39:31 kettenis Exp $ */ 2 /* PUBLIC DOMAIN Sep 2011 <guenther@openbsd.org> */ 3 4 /* 5 * Verify that &errno is different for each thread and is stable across 6 * context switches and in signal handlers 7 */ 8 9 #include <errno.h> 10 #include <signal.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <unistd.h> 14 15 #include "test.h" 16 17 int *main_errno, *t1_errno, *t2_errno, **handler_errno; 18 pthread_t main_tid, t1_tid, t2_tid; 19 20 enum state 21 { 22 START, 23 T1_START, 24 T1_SIGNAL, 25 T1_CHECK2, 26 T1_EXIT, 27 } state; 28 29 pthread_mutex_t m; 30 pthread_cond_t c; 31 sigset_t sigusr2; 32 33 static void 34 set_state(enum state new_state) 35 { 36 CHECKe(pthread_mutex_lock(&m)); 37 ASSERT(state == new_state - 1); 38 state = new_state; 39 CHECKe(pthread_cond_signal(&c)); 40 CHECKe(pthread_mutex_unlock(&m)); 41 } 42 43 static void 44 wait_for_state(enum state new_state) 45 { 46 CHECKe(pthread_mutex_lock(&m)); 47 while(state != new_state) 48 CHECKe(pthread_cond_wait(&c, &m)); 49 CHECKe(pthread_mutex_unlock(&m)); 50 } 51 52 53 /* 54 * Yes, pthread_self() isn't async-signal-safe in general, but it should 55 * be okay for the regress test here 56 */ 57 static void 58 act_handler(int signal) 59 { 60 ASSERT(signal == SIGUSR1); 61 if (handler_errno == &main_errno) { 62 CHECKe(write(STDOUT_FILENO, "m", 1)); 63 ASSERT(&errno == main_errno); 64 ASSERTe(errno, == EXDEV); 65 ASSERT(pthread_equal(t1_tid, pthread_self())); 66 } else if (handler_errno == &t1_errno) { 67 CHECKe(write(STDOUT_FILENO, "\n", 1)); 68 ASSERT(&errno == t1_errno); 69 ASSERTe(errno, == EXDEV); 70 ASSERT(pthread_equal(t1_tid, pthread_self())); 71 CHECKe(kill(getpid(), SIGUSR2)); 72 } else if (handler_errno == &t2_errno) { 73 CHECKe(write(STDOUT_FILENO, "2", 1)); 74 ASSERT(&errno == t2_errno); 75 ASSERTe(errno, == EXDEV); 76 ASSERT(pthread_equal(t2_tid, pthread_self())); 77 } else { 78 PANIC("unknown thread in act_handler!"); 79 } 80 } 81 82 void * 83 tmain(void *arg) 84 { 85 t1_errno = &errno; 86 ASSERT(t1_errno != main_errno); 87 ASSERT(*t1_errno == 0); 88 89 /* verify preservation across switch */ 90 errno = EXDEV; 91 92 wait_for_state(T1_START); 93 94 t1_tid = pthread_self(); 95 ASSERT(pthread_equal(main_tid, t1_tid) == 0); 96 ASSERT(&errno == t1_errno); 97 98 ASSERTe(*t1_errno, == EXDEV); 99 100 set_state(T1_SIGNAL); 101 ASSERT(&errno == t1_errno); 102 wait_for_state(T1_CHECK2); 103 104 ASSERT(&errno == t1_errno); 105 ASSERT(pthread_equal(t1_tid, pthread_self())); 106 107 set_state(T1_EXIT); 108 return (NULL); 109 } 110 111 int 112 main(int argc, char **argv) 113 { 114 struct sigaction act; 115 int r; 116 117 pthread_mutex_init(&m, NULL); 118 pthread_cond_init(&c, NULL); 119 state = START; 120 121 main_errno = &errno; 122 main_tid = pthread_self(); 123 124 act.sa_handler = act_handler; 125 sigemptyset(&act.sa_mask); 126 act.sa_flags = 0; 127 errno = 0; 128 CHECKe(sigaction(SIGUSR1, &act, NULL)); 129 ASSERT(*main_errno == 0); 130 ASSERT(errno == 0); 131 132 /* 133 * we'll use SIGUSR2 for signal state change from act_handler, 134 * detecting it with sigwait(), so block it now 135 */ 136 CHECKe(sigaction(SIGUSR2, &act, NULL)); 137 sigemptyset(&sigusr2); 138 sigaddset(&sigusr2, SIGUSR2); 139 CHECKr(pthread_sigmask(SIG_BLOCK, &sigusr2, NULL)); 140 141 sched_yield(); 142 ASSERT(&errno == main_errno); 143 144 /* do something to force an error */ 145 r = close(11); 146 if (r != 0) { 147 ASSERT(r == -1); 148 ASSERTe(*main_errno, == EBADF); 149 ASSERTe(errno, == EBADF); 150 } 151 r = write(11, "", 1); 152 ASSERT(r == -1); 153 ASSERTe(*main_errno, == EBADF); 154 ASSERTe(errno, == EBADF); 155 156 /* verify that a succesfull syscall doesn't change errno */ 157 CHECKe(write(STDOUT_FILENO, "X", 1)); 158 ASSERTe(*main_errno, == EBADF); 159 ASSERTe(errno, == EBADF); 160 ASSERT(&errno == main_errno); 161 162 CHECKr(pthread_create(&t1_tid, NULL, tmain, NULL)); 163 ASSERTe(*main_errno, == EBADF); 164 ASSERT(&errno == main_errno); 165 ASSERT(pthread_equal(main_tid, pthread_self())); 166 167 set_state(T1_START); 168 ASSERTe(*main_errno, == EBADF); 169 ASSERT(&errno == main_errno); 170 171 wait_for_state(T1_SIGNAL); 172 ASSERTe(*main_errno, == EBADF); 173 ASSERT(&errno == main_errno); 174 ASSERT(pthread_equal(main_tid, pthread_self())); 175 176 handler_errno = &t1_errno; 177 CHECKe(pthread_kill(t1_tid, SIGUSR1)); 178 ASSERT(&errno == main_errno); 179 180 CHECKr(sigwait(&sigusr2, &r)); 181 ASSERTe(*main_errno, == EBADF); 182 ASSERT(&errno == main_errno); 183 ASSERT(pthread_equal(main_tid, pthread_self())); 184 set_state(T1_CHECK2); 185 186 wait_for_state(T1_EXIT); 187 CHECKe(pthread_join(t1_tid, NULL)); 188 ASSERT(&errno == main_errno); 189 ASSERT(pthread_equal(main_tid, pthread_self())); 190 191 SUCCEED; 192 } 193