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
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
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 *
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