summaryrefslogtreecommitdiff
path: root/regress
diff options
context:
space:
mode:
Diffstat (limited to 'regress')
-rw-r--r--regress/lib/libpthread/blocked_fifo/blocked_fifo.c79
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;