]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
sigdelay: Add tests. master
authorBruno Haible <bruno@clisp.org>
Wed, 15 Apr 2026 11:45:58 +0000 (13:45 +0200)
committerBruno Haible <bruno@clisp.org>
Wed, 15 Apr 2026 11:46:08 +0000 (13:46 +0200)
* tests/test-sigdelay1.c: New file, based on
tests/test-pthread_sigmask1.c.
* tests/test-sigdelay2.c: New file, based on
tests/test-pthread_sigmask2.c.
* modules/sigdelay-tests: New file.

ChangeLog
modules/sigdelay-tests [new file with mode: 0644]
tests/test-sigdelay1.c [new file with mode: 0644]
tests/test-sigdelay2.c [new file with mode: 0644]

index b1079e902d66dbfc30c4afbba5b803dceb34b2a2..761d1edc0cb019cc4860a703c094946d4a13b2b2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2026-04-15  Bruno Haible  <bruno@clisp.org>
 
+       sigdelay: Add tests.
+       * tests/test-sigdelay1.c: New file, based on
+       tests/test-pthread_sigmask1.c.
+       * tests/test-sigdelay2.c: New file, based on
+       tests/test-pthread_sigmask2.c.
+       * modules/sigdelay-tests: New file.
+
        sigdelay: New module.
        * lib/sigdelay.h: New file.
        * lib/sigdelay.c: New file.
diff --git a/modules/sigdelay-tests b/modules/sigdelay-tests
new file mode 100644 (file)
index 0000000..2c56ff4
--- /dev/null
@@ -0,0 +1,20 @@
+Files:
+tests/test-sigdelay1.c
+tests/test-sigdelay2.c
+tests/virtualbox.h
+tests/macros.h
+
+Depends-on:
+inttypes-h
+sleep
+pthread-thread
+streq
+memeq
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-sigdelay1 test-sigdelay2
+check_PROGRAMS += test-sigdelay1 test-sigdelay2
+test_sigdelay1_LDADD = $(LDADD) @LIBTHREAD@
+test_sigdelay2_LDADD = $(LDADD) @LIBMULTITHREAD@
diff --git a/tests/test-sigdelay1.c b/tests/test-sigdelay1.c
new file mode 100644 (file)
index 0000000..a6b3e4b
--- /dev/null
@@ -0,0 +1,104 @@
+/* Test of sigdelay in a single-threaded program.
+   Copyright (C) 2011-2026 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2026.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "sigdelay.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "virtualbox.h"
+#include "macros.h"
+
+#if !(defined _WIN32 && !defined __CYGWIN__)
+
+static volatile int sigint_occurred;
+
+static void
+sigint_handler (_GL_UNUSED int sig)
+{
+  sigint_occurred++;
+}
+
+int
+main ()
+{
+  /* This test occasionally fails on Linux (glibc or musl libc), in a
+     VirtualBox VM with paravirtualization = Default or KVM, with ≥ 2 CPUs,
+     when "Nested VT-x/AMD-V" and "PAE/NX" are not both enabled.
+     Skip the test in this situation.  */
+  if (is_running_under_virtualbox_kvm () && num_cpus () > 1)
+    {
+      fputs ("Skipping test: avoiding VirtualBox bug with KVM paravirtualization\n",
+             stderr);
+      return 77;
+    }
+
+  signal (SIGINT, sigint_handler);
+
+  sigset_t set;
+  sigemptyset (&set);
+  sigaddset (&set, SIGINT);
+
+  /* Check error handling.  */
+  ASSERT (sigdelay (1729, &set, NULL) == -1);
+  ASSERT (errno == EINVAL);
+
+  /* Block SIGINT.  */
+  ASSERT (sigdelay (SIG_BLOCK, &set, NULL) == 0);
+
+  /* Request a SIGINT signal from outside.  */
+  char command[80];
+  intmax_t pid = getpid ();
+  sprintf (command, "sh -c 'sleep 1; kill -INT %"PRIdMAX"' &", pid);
+  ASSERT (system (command) == 0);
+
+  /* Wait.  */
+  sleep (2);
+
+  /* The signal should not have arrived yet, because it is blocked.  */
+  ASSERT (sigint_occurred == 0);
+
+  /* Unblock SIGINT.  */
+  ASSERT (sigdelay (SIG_UNBLOCK, &set, NULL) == 0);
+
+  /* The signal should have arrived now.  */
+  ASSERT (sigint_occurred == 1);
+
+  return test_exit_status;
+}
+
+#else
+
+/* On native Windows, getpid() values and the arguments that are passed to
+   the (Cygwin?) 'kill' program are not necessarily related.  */
+
+int
+main ()
+{
+  fputs ("Skipping test: native Windows platform\n", stderr);
+  return 77;
+}
+
+#endif
diff --git a/tests/test-sigdelay2.c b/tests/test-sigdelay2.c
new file mode 100644 (file)
index 0000000..7d15d6d
--- /dev/null
@@ -0,0 +1,143 @@
+/* Test of sigdelay in a multi-threaded process.
+   Copyright (C) 2011-2026 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2026.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "sigdelay.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "virtualbox.h"
+#include "macros.h"
+
+#if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS
+
+static pthread_t main_thread;
+static pthread_t killer_thread1;
+static pthread_t killer_thread2;
+
+static void *
+killer_thread1_func (_GL_UNUSED void *arg)
+{
+  sleep (1);
+  pthread_kill (main_thread, SIGINT);
+  return NULL;
+}
+
+static void *
+killer_thread2_func (_GL_UNUSED void *arg)
+{
+  sleep (1);
+  pthread_kill (pthread_self (), SIGINT);
+  return NULL;
+}
+
+static volatile int sigint_occurred;
+
+static void
+sigint_handler (_GL_UNUSED int sig)
+{
+  sigint_occurred++;
+}
+
+int
+main ()
+{
+  /* This test occasionally fails on Linux (glibc or musl libc), in a
+     VirtualBox VM with paravirtualization = Default or KVM, with ≥ 2 CPUs,
+     when "Nested VT-x/AMD-V" and "PAE/NX" are not both enabled.
+     Skip the test in this situation.  */
+  if (is_running_under_virtualbox_kvm () && num_cpus () > 1)
+    {
+      fputs ("Skipping test: avoiding VirtualBox bug with KVM paravirtualization\n",
+             stderr);
+      return 77;
+    }
+
+  signal (SIGINT, sigint_handler);
+
+  sigset_t set;
+  sigemptyset (&set);
+  sigaddset (&set, SIGINT);
+
+  /* Check error handling.  */
+  ASSERT (sigdelay (1729, &set, NULL) == -1);
+  ASSERT (errno == EINVAL);
+
+  /* Block SIGINT.  */
+  ASSERT (sigdelay (SIG_BLOCK, &set, NULL) == 0);
+
+  /* Request a SIGINT signal from another thread.  */
+  main_thread = pthread_self ();
+  ASSERT (pthread_create (&killer_thread1, NULL, killer_thread1_func, NULL)
+          == 0);
+
+  /* Wait.  */
+  sleep (2);
+
+  /* The signal should not have arrived yet, because it is blocked.  */
+  ASSERT (sigint_occurred == 0);
+
+  /* Unblock SIGINT.  */
+  ASSERT (sigdelay (SIG_UNBLOCK, &set, NULL) == 0);
+
+  /* The signal should have arrived now.  */
+  ASSERT (sigint_occurred == 1);
+
+  /* Request a SIGINT signal from another thread.  */
+  ASSERT (pthread_create (&killer_thread2, NULL, killer_thread2_func, NULL)
+          == 0);
+
+  /* Block SIGINT.  */
+  ASSERT (sigdelay (SIG_BLOCK, &set, NULL) == 0);
+
+  /* Wait.  */
+  sleep (2);
+
+  /* The signal should not have arrived yet, because it is blocked.  */
+  ASSERT (sigint_occurred == 1);
+
+  /* Unblock SIGINT.  */
+  ASSERT (sigdelay (SIG_UNBLOCK, &set, NULL) == 0);
+
+  /* The signal should have arrived now.  */
+  ASSERT (sigint_occurred == 2);
+
+  /* Clean up the threads.  This avoids a "ThreadSanitizer: thread leak" warning
+     from "gcc -fsanitize=thread".  */
+  ASSERT (pthread_join (killer_thread1, NULL) == 0);
+  ASSERT (pthread_join (killer_thread2, NULL) == 0);
+
+  return test_exit_status;
+}
+
+#else
+
+int
+main ()
+{
+  fputs ("Skipping test: POSIX threads not enabled\n", stderr);
+  return 77;
+}
+
+#endif