]> Savannah Git Hosting - gnulib.git/commitdiff
tests: Avoid test failures due to VirtualBox specific bug.
authorBruno Haible <bruno@clisp.org>
Sat, 29 Jun 2024 11:28:14 +0000 (13:28 +0200)
committerBruno Haible <bruno@clisp.org>
Sat, 29 Jun 2024 14:02:46 +0000 (16:02 +0200)
* tests/virtualbox.h: New file.
* tests/test-pthread-cond.c: Include virtualbox.h.
(main): Skip the test under VirtualBox with KVM paravirtualization and
more than 1 CPU.
* tests/test-cnd.c: Include virtualbox.h.
(main): Skip the test under VirtualBox with KVM paravirtualization and
more than 1 CPU.
* tests/test-cond.c: Include virtualbox.h.
(main): Skip the test under VirtualBox with KVM paravirtualization and
more than 1 CPU.
* tests/test-pthread_sigmask1.c: Include virtualbox.h.
(main): Skip the test under VirtualBox with KVM paravirtualization and
more than 1 CPU.
* tests/test-pthread_sigmask2.c: Include virtualbox.h.
(main): Skip the test under VirtualBox with KVM paravirtualization and
more than 1 CPU.
* tests/test-sigprocmask.c: Include virtualbox.h.
(main): Skip the test under VirtualBox with KVM paravirtualization and
more than 1 CPU.
* modules/pthread-cond-tests (Files): Add tests/virtualbox.h.
* modules/cnd-tests (Files): Likewise.
* modules/cond-tests (Files): Likewise.
* modules/pthread_sigmask-tests (Files): Likewise.
* modules/sigprocmask-tests (Files): Likewise.

13 files changed:
ChangeLog
modules/cnd-tests
modules/cond-tests
modules/pthread-cond-tests
modules/pthread_sigmask-tests
modules/sigprocmask-tests
tests/test-cnd.c
tests/test-cond.c
tests/test-pthread-cond.c
tests/test-pthread_sigmask1.c
tests/test-pthread_sigmask2.c
tests/test-sigprocmask.c
tests/virtualbox.h [new file with mode: 0644]

index 6d5caed394b03b9efc9770d87802aeab2a91808a..30424d8fbcb40c26a692bddabe09b7ae1273cac4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2024-06-29  Bruno Haible  <bruno@clisp.org>
+
+       tests: Avoid test failures due to VirtualBox specific bug.
+       * tests/virtualbox.h: New file.
+       * tests/test-pthread-cond.c: Include virtualbox.h.
+       (main): Skip the test under VirtualBox with KVM paravirtualization and
+       more than 1 CPU.
+       * tests/test-cnd.c: Include virtualbox.h.
+       (main): Skip the test under VirtualBox with KVM paravirtualization and
+       more than 1 CPU.
+       * tests/test-cond.c: Include virtualbox.h.
+       (main): Skip the test under VirtualBox with KVM paravirtualization and
+       more than 1 CPU.
+       * tests/test-pthread_sigmask1.c: Include virtualbox.h.
+       (main): Skip the test under VirtualBox with KVM paravirtualization and
+       more than 1 CPU.
+       * tests/test-pthread_sigmask2.c: Include virtualbox.h.
+       (main): Skip the test under VirtualBox with KVM paravirtualization and
+       more than 1 CPU.
+       * tests/test-sigprocmask.c: Include virtualbox.h.
+       (main): Skip the test under VirtualBox with KVM paravirtualization and
+       more than 1 CPU.
+       * modules/pthread-cond-tests (Files): Add tests/virtualbox.h.
+       * modules/cnd-tests (Files): Likewise.
+       * modules/cond-tests (Files): Likewise.
+       * modules/pthread_sigmask-tests (Files): Likewise.
+       * modules/sigprocmask-tests (Files): Likewise.
+
 2024-06-28  Collin Funk  <collin.funk1@gmail.com>
 
        doc: Mention the byteswap module in function documentation.
index f9dc79ea7d6be80f8c6766d391431c320fe3aea5..be3c9de0a6cd1691b76ece900d0dd87b32ccfc51 100644 (file)
@@ -1,5 +1,6 @@
 Files:
 tests/test-cnd.c
+tests/virtualbox.h
 tests/macros.h
 
 Depends-on:
index 6b4c45e2c00db9da83110fc146f478174d582ffe..d984ca84b1d0a36f2e44a13d3d0845fc9e155c84 100644 (file)
@@ -1,5 +1,6 @@
 Files:
 tests/test-cond.c
+tests/virtualbox.h
 
 Depends-on:
 lock
index fc0a1c8e064e062655cfa8e1171faf9785fb4a90..baafb48993fad7e08d11a32f749c3396d62419fe 100644 (file)
@@ -1,5 +1,6 @@
 Files:
 tests/test-pthread-cond.c
+tests/virtualbox.h
 tests/macros.h
 
 Depends-on:
index 00185a0d3e2bee20d8e00f69ada71480813f630d..508c02a16f476ac1f7139be573545ea87bfa3613 100644 (file)
@@ -2,6 +2,7 @@ Files:
 tests/test-pthread_sigmask1.c
 tests/test-pthread_sigmask2.c
 tests/signature.h
+tests/virtualbox.h
 tests/macros.h
 
 Depends-on:
index 8e6523e78503bc3a99daf0a5f1e98b1b0d62af8c..7880b64b9b7b2c097e6a24992183b9b1d7589ed0 100644 (file)
@@ -1,6 +1,7 @@
 Files:
 tests/test-sigprocmask.c
 tests/signature.h
+tests/virtualbox.h
 tests/macros.h
 
 Depends-on:
index b8906a15c0d8b7b16db315c1610c148530fac00b..bcd0e7786c52d0a0872f587432f8ff979b586993 100644 (file)
@@ -41,6 +41,7 @@
 # include <unistd.h>
 #endif
 
+#include "virtualbox.h"
 #include "macros.h"
 
 #if ENABLE_DEBUGGING
@@ -230,6 +231,16 @@ test_cnd_timedwait (void)
 int
 main ()
 {
+  /* This test occasionally fails on Linux (glibc or musl libc), in a
+     VirtualBox VM with paravirtualization = Default or KVM, with ≥ 2 CPUs.
+     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;
+    }
+
 #if HAVE_DECL_ALARM
   /* Declare failure if test takes too long, by using default abort
      caused by SIGALRM.  */
index 712220aaac39c7eb52286a7aebcd99f56d05d61e..113dd392f6cad99332468d189cfb3bf0c35e95ab 100644 (file)
@@ -43,6 +43,8 @@
 #include "glthread/thread.h"
 #include "glthread/yield.h"
 
+#include "virtualbox.h"
+
 #if ENABLE_DEBUGGING
 # define dbgprintf printf
 #else
@@ -219,6 +221,16 @@ test_timedcond (void)
 int
 main ()
 {
+  /* This test occasionally fails on Linux (glibc or musl libc), in a
+     VirtualBox VM with paravirtualization = Default or KVM, with ≥ 2 CPUs.
+     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;
+    }
+
 #if DO_TEST_COND
   printf ("Starting test_cond ..."); fflush (stdout);
   {
index 3854ee2745208b9ad861cf63e71169d2ec1a8d95..3f621fa17a38770fecd470149293a174f2d1065b 100644 (file)
@@ -46,6 +46,7 @@
 # include <unistd.h>
 #endif
 
+#include "virtualbox.h"
 #include "macros.h"
 
 #if ENABLE_DEBUGGING
@@ -237,6 +238,16 @@ test_pthread_cond_timedwait (void)
 int
 main ()
 {
+  /* This test occasionally fails on Linux (glibc or musl libc), in a
+     VirtualBox VM with paravirtualization = Default or KVM, with ≥ 2 CPUs.
+     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;
+    }
+
 #if HAVE_DECL_ALARM
   /* Declare failure if test takes too long, by using default abort
      caused by SIGALRM.  */
index 93ed7eb1723ec54df198cf52666d2f8699644e13..aa7efd65f4684fb06c38f3e57694c5898cb7da6d 100644 (file)
@@ -29,6 +29,7 @@ SIGNATURE_CHECK (pthread_sigmask, int, (int, const sigset_t *, sigset_t *));
 #include <stdlib.h>
 #include <unistd.h>
 
+#include "virtualbox.h"
 #include "macros.h"
 
 #if !(defined _WIN32 && !defined __CYGWIN__)
@@ -44,6 +45,16 @@ sigint_handler (_GL_UNUSED int sig)
 int
 main ()
 {
+  /* This test occasionally fails on Linux (glibc or musl libc), in a
+     VirtualBox VM with paravirtualization = Default or KVM, with ≥ 2 CPUs.
+     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;
+    }
+
   sigset_t set;
   intmax_t pid = getpid ();
   char command[80];
index fa3c1d8d91870edb00a8fd903f378e5a2a1f2fce..a847e6b3b3ecdfd6b54a76ab156b46bd4c5cc7d9 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <unistd.h>
 
+#include "virtualbox.h"
 #include "macros.h"
 
 #if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS
@@ -51,6 +52,16 @@ sigint_handler (_GL_UNUSED int sig)
 int
 main ()
 {
+  /* This test occasionally fails on Linux (glibc or musl libc), in a
+     VirtualBox VM with paravirtualization = Default or KVM, with ≥ 2 CPUs.
+     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;
+    }
+
   sigset_t set;
 
   signal (SIGINT, sigint_handler);
index 30c04e5b72f14e8d23175f14cfd541048ab779ba..b9cdb6b0639104f7ff726bb055deade9ebd92ed1 100644 (file)
@@ -29,6 +29,7 @@ SIGNATURE_CHECK (sigprocmask, int, (int, const sigset_t *, sigset_t *));
 #include <stdlib.h>
 #include <unistd.h>
 
+#include "virtualbox.h"
 #include "macros.h"
 
 #if !(defined _WIN32 && !defined __CYGWIN__)
@@ -44,6 +45,16 @@ sigint_handler (_GL_UNUSED int sig)
 int
 main ()
 {
+  /* This test occasionally fails on Linux (glibc or musl libc), in a
+     VirtualBox VM with paravirtualization = Default or KVM, with ≥ 2 CPUs.
+     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;
+    }
+
   sigset_t set;
   intmax_t pid = getpid ();
   char command[80];
diff --git a/tests/virtualbox.h b/tests/virtualbox.h
new file mode 100644 (file)
index 0000000..86a47fa
--- /dev/null
@@ -0,0 +1,134 @@
+/* Determine whether the current system is running under VirtualBox/KVM.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2024.  */
+
+#ifdef __linux__
+# include <fcntl.h>
+# include <string.h>
+# include <unistd.h>
+#endif
+
+/* This function determines whether the current system is Linux and running
+   under the VirtualBox emulator.  */
+static bool
+is_running_under_virtualbox (void)
+{
+#ifdef __linux__
+  /* On distributions with systemd, this could be done through
+       test `systemd-detect-virt --vm` = oracle
+     More generally, it can be done through
+       test "`cat /sys/class/dmi/id/product_name`" = VirtualBox
+     This is what we do here.  */
+  char buf[4096];
+  int fd = open ("/sys/class/dmi/id/product_name", O_RDONLY);
+  if (fd >= 0)
+    {
+      int n = read (fd, buf, sizeof (buf));
+      close (fd);
+      if (n == 10 + 1 && memcmp (buf, "VirtualBox\n", 10 + 1) == 0)
+        return true;
+    }
+#endif
+
+  return false;
+}
+
+/* This function determines whether the current system is Linux and running
+   under the VirtualBox emulator, with paravirtualization acceleration set to
+   "Default" or "KVM".  */
+static bool
+is_running_under_virtualbox_kvm (void)
+{
+#ifdef __linux__
+  if (is_running_under_virtualbox ())
+    {
+      /* As root, one can determine this paravirtualization mode through
+           dmesg | grep -i kvm
+         which produces output like this:
+           [    0.000000] Hypervisor detected: KVM
+           [    0.000000] kvm-clock: Using msrs 4b564d01 and 4b564d00
+           [    0.000001] kvm-clock: using sched offset of 3736655524 cycles
+           [    0.000004] clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
+           [    0.007355] Booting paravirtualized kernel on KVM
+           [    0.213538] clocksource: Switched to clocksource kvm-clock
+         So, we test whether the file
+         /sys/devices/system/clocksource/clocksource0/available_clocksource
+         contains the word 'kvm-clock'.  */
+      char buf[4096 + 1];
+      int fd = open ("/sys/devices/system/clocksource/clocksource0/available_clocksource", O_RDONLY);
+      if (fd >= 0)
+        {
+          int n = read (fd, buf, sizeof (buf) - 1);
+          close (fd);
+          if (n > 0)
+            {
+              buf[n] = '\0';
+              char *saveptr;
+              char *word;
+              for (word = strtok_r (buf, " \n", &saveptr);
+                   word != NULL;
+                   word = strtok_r (NULL, " \n", &saveptr))
+                {
+                  if (strcmp (word, "kvm-clock") == 0)
+                    return true;
+                }
+            }
+        }
+    }
+#endif
+
+  return false;
+}
+
+/* This function returns the number of CPUs in the current system, assuming
+   it is Linux.  */
+static int
+num_cpus (void)
+{
+#ifdef __linux__
+  /* We could use sysconf (_SC_NPROCESSORS_CONF), which on glibc and musl libc
+     is implemented through sched_getaffinity().  But there are some
+     complications; see nproc.c.  It's simpler to parse /proc/cpuinfo.
+     More precisely, it's sufficient to count the number of blank lines in
+     /proc/cpuinfo.  */
+  char buf[4096];
+  int fd = open ("/proc/cpuinfo", O_RDONLY);
+  if (fd >= 0)
+    {
+      unsigned int blank_lines = 0;
+      bool last_char_was_newline = false;
+      for (;;)
+        {
+          int n = read (fd, buf, sizeof (buf));
+          if (n <= 0)
+            break;
+          int i;
+          for (i = 0; i < n; i++)
+            {
+              if (last_char_was_newline && buf[i] == '\n')
+                blank_lines++;
+              last_char_was_newline = (buf[i] == '\n');
+            }
+        }
+      close (fd);
+      if (blank_lines > 0)
+        return blank_lines;
+    }
+#endif
+
+  return 1;
+}