diff options
Diffstat (limited to 'src/util/fifo_rdonly_bug.c')
-rw-r--r-- | src/util/fifo_rdonly_bug.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/util/fifo_rdonly_bug.c b/src/util/fifo_rdonly_bug.c new file mode 100644 index 0000000..bf93467 --- /dev/null +++ b/src/util/fifo_rdonly_bug.c @@ -0,0 +1,127 @@ +/*++ +/* NAME +/* fifo_rdonly_bug 1 +/* SUMMARY +/* fifo server test program +/* SYNOPSIS +/* fifo_rdonly_bug +/* DESCRIPTION +/* fifo_rdonly_bug creates a FIFO and opens it read only. It +/* then opens the FIFO for writing, writes one byte, and closes +/* the writing end. On Linux Redhat 4.2 and 5.0, and HP-UX 9.05 +/* and 10.20, select() will report that the FIFO remains readable +/* even after multiple read operations. +/* DIAGNOSTICS +/* Problems are reported to the standard error stream. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#include <sys_defs.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> + +#define FIFO_PATH "test-fifo" +#define TRIGGER_DELAY 5 + +#define perrorexit(s) { perror(s); exit(1); } + +static void cleanup(void) +{ + printf("Removing fifo %s...\n", FIFO_PATH); + if (unlink(FIFO_PATH)) + perrorexit("unlink"); + printf("Done.\n"); +} + +static void perrorcleanup(char *str) +{ + perror(str); + cleanup(); + exit(0); +} + +static void readable_event(int fd) +{ + char ch; + static int count = 0; + + if (read(fd, &ch, 1) < 0) { + perror("read"); + sleep(1); + } + if (count++ > 5) { + printf("FIFO remains readable after multiple reads.\n"); + cleanup(); + exit(1); + } +} + +int main(int unused_argc, char **unused_argv) +{ + struct timeval tv; + fd_set read_fds; + fd_set except_fds; + int fd; + int fd2; + + (void) unlink(FIFO_PATH); + + printf("Create fifo %s...\n", FIFO_PATH); + if (mkfifo(FIFO_PATH, 0600) < 0) + perrorexit("mkfifo"); + + printf("Open fifo %s, read-only mode...\n", FIFO_PATH); + if ((fd = open(FIFO_PATH, O_RDONLY | O_NONBLOCK, 0)) < 0) + perrorcleanup("open"); + + printf("Write one byte to the fifo, then close it...\n"); + if ((fd2 = open(FIFO_PATH, O_WRONLY, 0)) < 0) + perrorcleanup("open fifo O_WRONLY"); + if (write(fd2, "", 1) < 1) + perrorcleanup("write one byte to fifo"); + if (close(fd2) < 0) + perrorcleanup("close fifo"); + + printf("Selecting the fifo for readability...\n"); + + for (;;) { + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + FD_ZERO(&except_fds); + FD_SET(fd, &except_fds); + tv.tv_sec = 1; + tv.tv_usec = 0; + + switch (select(fd + 1, &read_fds, (fd_set *) 0, &except_fds, &tv)) { + case -1: + perrorexit("select"); + default: + if (FD_ISSET(fd, &except_fds)) { + printf("Exceptional fifo condition! You are not normal!\n"); + readable_event(fd); + } else if (FD_ISSET(fd, &read_fds)) { + printf("Readable fifo condition\n"); + readable_event(fd); + } + break; + case 0: + printf("The fifo is not readable. You're normal.\n"); + cleanup(); + exit(0); + break; + } + } +} |