about summary refs log tree commit diff
path: root/misc
diff options
context:
space:
mode:
Diffstat (limited to 'misc')
-rw-r--r--misc/Makefile2
-rw-r--r--misc/tst-pselect.c120
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"