1 /* $OpenBSD: sem_wait.c,v 1.3 2012/03/03 09:51:00 guenther Exp $ */
2 /*
3 * Martin Pieuchot <mpi@openbsd.org>, 2011. Public Domain.
4 */
5
6 #include <err.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <semaphore.h>
10 #include <signal.h>
11 #include <pthread.h>
12 #include "test.h"
13
14
15 void *waiter(void *arg);
16
17 void
handler(int sig)18 handler(int sig)
19 {
20 static char message[] = "got sig\n";
21
22 write(STDERR_FILENO, message, sizeof(message) - 1);
23 }
24
25 sem_t sem;
26 volatile int posted = 0, eintr_ok = 0;
27
28 int
main(int argc,char ** argv)29 main(int argc, char **argv)
30 {
31 pthread_t th;
32 struct sigaction sa;
33
34 CHECKn(sem_wait(&sem));
35 ASSERT(errno == EINVAL);
36
37 CHECKr(sem_init(&sem, 0, 0));
38
39 CHECKr(pthread_create(&th, NULL, waiter, &sem));
40
41 sleep(1);
42
43 printf("expect: sem_destroy on semaphore with waiters!\n");
44 CHECKn(sem_destroy(&sem));
45 ASSERT(errno == EBUSY);
46
47 posted = 1;
48 CHECKr(sem_post(&sem));
49 CHECKr(pthread_join(th, NULL));
50
51 /* test that sem_wait() resumes after handling a signal */
52 memset(&sa, 0, sizeof sa);
53 sa.sa_handler = &handler;
54 sigemptyset(&sa.sa_mask);
55 sa.sa_flags = 0;
56 if (sigaction(SIGUSR1, &sa, NULL))
57 err(1, "sigaction");
58 posted = 0;
59 CHECKr(pthread_create(&th, NULL, waiter, &sem));
60 sleep(1);
61 fprintf(stderr, "sending sig\n");
62 eintr_ok = 1;
63 pthread_kill(th, SIGUSR1);
64 sleep(1);
65 fprintf(stderr, "posting\n");
66 posted = 1;
67 eintr_ok = 0;
68 CHECKr(sem_post(&sem));
69 CHECKr(pthread_join(th, NULL));
70
71 CHECKe(sem_destroy(&sem));
72
73 SUCCEED;
74 }
75
76 void *
waiter(void * arg)77 waiter(void *arg)
78 {
79 sem_t *semp = arg;
80 int value;
81 int r;
82
83 r = sem_wait(semp);
84 CHECKr(sem_getvalue(semp, &value));
85 if (r == 0) {
86 ASSERT(value == 0);
87 ASSERT(posted != 0);
88 } else {
89 ASSERT(r == -1);
90 ASSERT(errno == EINTR);
91 ASSERT(eintr_ok);
92 if (posted)
93 ASSERT(value == 1);
94 else
95 ASSERT(value == 0);
96 }
97
98 return (NULL);
99 }
100