diff options
Diffstat (limited to 'misc')
-rw-r--r-- | misc/Makefile | 2 | ||||
-rw-r--r-- | misc/tst-pselect.c | 120 |
2 files changed, 121 insertions, 1 deletions
diff --git a/misc/Makefile b/misc/Makefile index dc993c4174..7d60baa7d6 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -77,7 +77,7 @@ endif gpl2lgpl := error.c error.h tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ - tst-error1 + tst-error1 tst-pselect ifeq (no,$(cross-compiling)) tests: $(objpfx)tst-error1-mem endif diff --git a/misc/tst-pselect.c b/misc/tst-pselect.c new file mode 100644 index 0000000000..55253ded84 --- /dev/null +++ b/misc/tst-pselect.c @@ -0,0 +1,120 @@ +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <sys/select.h> +#include <sys/wait.h> + + +static volatile int handler_called; + +static void +handler (int sig) +{ + handler_called = 1; +} + + +static int +do_test (void) +{ + struct sigaction sa; + sa.sa_handler = handler; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + + if (sigaction (SIGUSR1, &sa, NULL) != 0) + { + puts ("sigaction failed"); + return 1; + } + + if (sigblock (SIGUSR1) != 0) + { + puts ("sigblock failed"); + return 1; + } + + int fds[2][2]; + + if (pipe (fds[0]) != 0 || pipe (fds[1]) != 0) + { + puts ("pipe failed"); + return 1; + } + + fd_set rfds; + FD_ZERO (&rfds); + + sigset_t ss; + sigprocmask (SIG_SETMASK, NULL, &ss); + sigdelset (&ss, SIGUSR1); + + struct timespec to = { .tv_sec = 0, .tv_nsec = 500000000 }; + + pid_t p = fork (); + if (p == 0) + { + close (fds[0][1]); + close (fds[1][0]); + + FD_SET (fds[0][0], &rfds); + + int e; + do + { + errno = 0; + e = pselect (fds[0][0] + 1, &rfds, NULL, NULL, &to, &ss); + } + while (e == 0); + + if (e != -1) + { + puts ("child: pselect did not fail"); + return 0; + } + if (errno != EINTR) + { + puts ("child: pselect did not set errno to EINTR"); + return 0; + } + + TEMP_FAILURE_RETRY (write (fds[1][1], "foo", 3)); + + exit (0); + } + + close (fds[0][0]); + close (fds[1][1]); + + FD_SET (fds[1][0], &rfds); + + kill (p, SIGUSR1); + + int e = pselect (fds[1][0] + 1, &rfds, NULL, NULL, NULL, &ss); + if (e == -1) + { + puts ("parent: pselect failed"); + return 1; + } + if (e != 1) + { + puts ("parent: pselect did not report readable fd"); + return 1; + } + if (!FD_ISSET (fds[1][0], &rfds)) + { + puts ("parent: pselect reports wrong fd"); + return 1; + } + + if (TEMP_FAILURE_RETRY (waitpid (p, NULL, 0)) != p) + { + puts ("waitpid failed"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |