diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-03-03 09:51:01 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-03-03 09:51:01 +0000 |
commit | d3eb35cce401703fd2ae4cd22bfab4a2092ac3ee (patch) | |
tree | 0521b1ceeaaa24492c9f65309a688dc7e24a3e35 | |
parent | 462c0d8565fe9be3b04859e23ba086228eb24cf4 (diff) |
Verify that sem_wait() doesn't return zero without decrementing the
semaphore when a signal is received. It should either resume waiting
or return EINTR, preferrably the former.
-rw-r--r-- | regress/lib/libpthread/semaphore/sem_wait/sem_wait.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/regress/lib/libpthread/semaphore/sem_wait/sem_wait.c b/regress/lib/libpthread/semaphore/sem_wait/sem_wait.c index efc3e932ffe..725b639c634 100644 --- a/regress/lib/libpthread/semaphore/sem_wait/sem_wait.c +++ b/regress/lib/libpthread/semaphore/sem_wait/sem_wait.c @@ -1,23 +1,35 @@ -/* $OpenBSD: sem_wait.c,v 1.2 2012/03/03 09:36:26 guenther Exp $ */ +/* $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); @@ -28,9 +40,31 @@ main(int argc, char **argv) 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)); @@ -43,8 +77,23 @@ void * waiter(void *arg) { sem_t *semp = arg; - - CHECKr(sem_wait(semp)); + 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); } |