summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2012-03-03 09:51:01 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2012-03-03 09:51:01 +0000
commitd3eb35cce401703fd2ae4cd22bfab4a2092ac3ee (patch)
tree0521b1ceeaaa24492c9f65309a688dc7e24a3e35
parent462c0d8565fe9be3b04859e23ba086228eb24cf4 (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.c55
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);
}