1 /* $OpenBSD: errno.c,v 1.2 2012/02/20 02:34:33 guenther 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 errno = ENODEV; 72 CHECKe(kill(getpid(), SIGUSR2)); 73 ASSERTe(errno, == ENODEV); 74 } else if (handler_errno == &t2_errno) { 75 CHECKe(write(STDOUT_FILENO, "2", 1)); 76 ASSERT(&errno == t2_errno); 77 ASSERTe(errno, == EXDEV); 78 ASSERT(pthread_equal(t2_tid, pthread_self())); 79 } else { 80 PANIC("unknown thread in act_handler!"); 81 } 82 } 83 84 void * 85 tmain(void *arg) 86 { 87 t1_errno = &errno; 88 ASSERT(t1_errno != main_errno); 89 ASSERT(*t1_errno == 0); 90 91 /* verify preservation across switch */ 92 errno = EXDEV; 93 94 wait_for_state(T1_START); 95 96 t1_tid = pthread_self(); 97 ASSERT(pthread_equal(main_tid, t1_tid) == 0); 98 ASSERT(&errno == t1_errno); 99 100 ASSERTe(*t1_errno, == EXDEV); 101 102 set_state(T1_SIGNAL); 103 ASSERT(&errno == t1_errno); 104 wait_for_state(T1_CHECK2); 105 ASSERTe(*t1_errno, == ENODEV); 106 107 ASSERT(&errno == t1_errno); 108 ASSERT(pthread_equal(t1_tid, pthread_self())); 109 110 set_state(T1_EXIT); 111 return (NULL); 112 } 113 114 int 115 main(int argc, char **argv) 116 { 117 struct sigaction act; 118 int r; 119 120 pthread_mutex_init(&m, NULL); 121 pthread_cond_init(&c, NULL); 122 state = START; 123 124 main_errno = &errno; 125 main_tid = pthread_self(); 126 127 act.sa_handler = act_handler; 128 sigemptyset(&act.sa_mask); 129 act.sa_flags = 0; 130 errno = 0; 131 CHECKe(sigaction(SIGUSR1, &act, NULL)); 132 ASSERT(*main_errno == 0); 133 ASSERT(errno == 0); 134 135 /* 136 * we'll use SIGUSR2 for signal state change from act_handler, 137 * detecting it with sigwait(), so block it now 138 */ 139 CHECKe(sigaction(SIGUSR2, &act, NULL)); 140 sigemptyset(&sigusr2); 141 sigaddset(&sigusr2, SIGUSR2); 142 CHECKr(pthread_sigmask(SIG_BLOCK, &sigusr2, NULL)); 143 144 sched_yield(); 145 ASSERT(&errno == main_errno); 146 147 /* do something to force an error */ 148 r = close(11); 149 if (r != 0) { 150 ASSERT(r == -1); 151 ASSERTe(*main_errno, == EBADF); 152 ASSERTe(errno, == EBADF); 153 } 154 r = write(11, "", 1); 155 ASSERT(r == -1); 156 ASSERTe(*main_errno, == EBADF); 157 ASSERTe(errno, == EBADF); 158 159 /* verify that a succesfull syscall doesn't change errno */ 160 CHECKe(write(STDOUT_FILENO, "X", 1)); 161 ASSERTe(*main_errno, == EBADF); 162 ASSERTe(errno, == EBADF); 163 ASSERT(&errno == main_errno); 164 165 CHECKr(pthread_create(&t1_tid, NULL, tmain, NULL)); 166 ASSERTe(*main_errno, == EBADF); 167 ASSERT(&errno == main_errno); 168 ASSERT(pthread_equal(main_tid, pthread_self())); 169 170 set_state(T1_START); 171 ASSERTe(*main_errno, == EBADF); 172 ASSERT(&errno == main_errno); 173 174 wait_for_state(T1_SIGNAL); 175 ASSERTe(*main_errno, == EBADF); 176 ASSERT(&errno == main_errno); 177 ASSERT(pthread_equal(main_tid, pthread_self())); 178 179 180 handler_errno = &t1_errno; 181 CHECKe(pthread_kill(t1_tid, SIGUSR1)); 182 ASSERT(&errno == main_errno); 183 184 CHECKr(sigwait(&sigusr2, &r)); 185 ASSERTe(*main_errno, == EBADF); 186 ASSERT(&errno == main_errno); 187 ASSERT(pthread_equal(main_tid, pthread_self())); 188 set_state(T1_CHECK2); 189 190 wait_for_state(T1_EXIT); 191 CHECKe(pthread_join(t1_tid, NULL)); 192 ASSERT(&errno == main_errno); 193 ASSERT(pthread_equal(main_tid, pthread_self())); 194 195 SUCCEED; 196 } 197