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