diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-07-08 11:35:38 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-07-08 11:35:38 +0000 |
commit | 12e40267e6c681fb7cb06dfbc555ac47ccf2ec3d (patch) | |
tree | 5d307103d4e4aa114acbbea297a6905cbfdab3e3 | |
parent | 5db65bec6120c09b52d705a8763c2087533a3beb (diff) |
Enhance the blocking test and add a test for closing while half-open
-rw-r--r-- | regress/lib/libpthread/blocked_fifo/blocked_fifo.c | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/regress/lib/libpthread/blocked_fifo/blocked_fifo.c b/regress/lib/libpthread/blocked_fifo/blocked_fifo.c index c5dc63bc45d..3b50f86878e 100644 --- a/regress/lib/libpthread/blocked_fifo/blocked_fifo.c +++ b/regress/lib/libpthread/blocked_fifo/blocked_fifo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: blocked_fifo.c,v 1.1 2012/03/19 17:41:57 oga Exp $ */ +/* $OpenBSD: blocked_fifo.c,v 1.2 2012/07/08 11:35:37 guenther Exp $ */ /* * Copyright (c) 2012 Owain G. Ainsworth <oga@openbsd.org> * @@ -30,9 +30,11 @@ #include <fcntl.h> #include "test.h" -#define FIFO "/tmp/pthread.fifo" +#define FIFO "pthread.fifo" #define FILE "/etc/services" /* just any file to deadlock on */ +int free_fd, expected_fd; + static void * deadlock_detector(void *arg) { @@ -55,6 +57,30 @@ fifo_deadlocker(void *arg) /* open fifo to unblock other thread */ CHECKe(fd = open(FIFO, O_WRONLY)); + CHECKe(write(fd, "test", 4)); + CHECKe(close(fd)); + + return ((caddr_t)NULL + errno); +} + +static void * +fifo_closer(void *arg) +{ + int fd; + + /* let other fifo open start */ + sleep(3); + + /* open a random temporary file and dup2 it over the FIFO */ + CHECKe(fd = open(FILE, O_RDONLY)); + CHECKe(dup2(fd, expected_fd)); + CHECKe(close(fd)); + CHECKe(close(expected_fd)); + + /* open fifo to unblock other thread */ + CHECKe(fd = open(FIFO, O_WRONLY)); + CHECKe(write(fd, "test", 4)); + CHECKe(close(fd)); return ((caddr_t)NULL + errno); } @@ -62,21 +88,60 @@ fifo_deadlocker(void *arg) int main(int argc, char *argv[]) { - pthread_t deadlock_thread, deadlock_finder; + pthread_t test_thread, deadlock_finder; + struct stat st; + char buf[5]; int fd; + ssize_t rlen; + unlink(FIFO); CHECKe(mkfifo(FIFO, S_IRUSR | S_IWUSR)); - CHECKr(pthread_create(&deadlock_thread, NULL, - fifo_deadlocker, NULL)); CHECKr(pthread_create(&deadlock_finder, NULL, deadlock_detector, NULL)); - /* Open fifo (this will sleep until we have readers */ + /* + * Verify that other threads can still do fd-table operations + * while a thread is blocked opening a FIFO + */ + CHECKr(pthread_create(&test_thread, NULL, fifo_deadlocker, NULL)); + + /* Open fifo (this will sleep until we have readers) */ + CHECKe(fd = open(FIFO, O_RDONLY)); + + CHECKe(fstat(fd, &st)); + ASSERT(S_ISFIFO(st.st_mode)); + CHECKe(rlen = read(fd, buf, sizeof buf)); + ASSERT(rlen == 4); + + CHECKr(pthread_join(test_thread, NULL)); + + CHECKe(close(fd)); + + + /* + * Verify that if a thread is blocked opening a FIFO and another + * thread targets the half-open fd with dup2 that it doesn't blow up. + */ + CHECKr(pthread_create(&test_thread, NULL, fifo_closer, NULL)); + + free_fd = open("/dev/null", O_RDONLY); + expected_fd = dup(free_fd); + close(expected_fd); + + /* Open fifo (this will sleep until we have readers) */ CHECKe(fd = open(FIFO, O_RDONLY)); - CHECKr(pthread_join(deadlock_thread, NULL)); + ASSERT(fd == expected_fd); + ASSERT(close(fd) == -1); + ASSERT(errno == EBADF); + + CHECKr(pthread_join(test_thread, NULL)); + + CHECKe(close(free_fd)); + + /* clean up */ unlink(FIFO); SUCCEED; |