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