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