From ee8cfbc434de21cd92e64de28696ab7df5848dc0 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 21 Oct 2016 00:02:10 +0000 Subject: [PATCH] Add libc_test to workaround pth_cond_destroy_busy test hangs. This is a workaround for bug #371396. It adds a new test program that can be used skip tests given a specific libc implementation and optionally a specific minimum version. Currently only glibc is recognized. This is used for the drd and helgrind tests pth_cond_destroy_busy to be skipped on glibc 2.24.90+. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16097 --- drd/tests/pth_cond_destroy_busy.vgtest | 2 +- helgrind/tests/pth_cond_destroy_busy.vgtest | 2 +- tests/Makefile.am | 1 + tests/libc_test.c | 78 +++++++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tests/libc_test.c diff --git a/drd/tests/pth_cond_destroy_busy.vgtest b/drd/tests/pth_cond_destroy_busy.vgtest index eafbd7473a..f3cf778252 100644 --- a/drd/tests/pth_cond_destroy_busy.vgtest +++ b/drd/tests/pth_cond_destroy_busy.vgtest @@ -1,2 +1,2 @@ -prereq: ./supported_libpthread +prereq: ./supported_libpthread && ! ../../tests/libc_test glibc 2.24.90 prog: pth_cond_destroy_busy diff --git a/helgrind/tests/pth_cond_destroy_busy.vgtest b/helgrind/tests/pth_cond_destroy_busy.vgtest index 45d7853c0e..2957cc3266 100644 --- a/helgrind/tests/pth_cond_destroy_busy.vgtest +++ b/helgrind/tests/pth_cond_destroy_busy.vgtest @@ -1,2 +1,2 @@ -prereq: ! ../../tests/os_test darwin +prereq: ! ../../tests/os_test darwin && ! ../../tests/libc_test glibc 2.24.90 prog: ../../drd/tests/pth_cond_destroy_busy diff --git a/tests/Makefile.am b/tests/Makefile.am index 9c0cc3a053..7233626647 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,7 @@ noinst_HEADERS = \ check_PROGRAMS = \ arch_test \ os_test \ + libc_test \ true \ x86_amd64_features \ s390x_features \ diff --git a/tests/libc_test.c b/tests/libc_test.c new file mode 100644 index 0000000000..0de3d5de8d --- /dev/null +++ b/tests/libc_test.c @@ -0,0 +1,78 @@ +// Compare given libc name and version number to system name and version. + +// Returns +// - 0 if the libc name matches is at least the minimum version (if given). +// - 1 if the libc name doesn't match or the version is lower than requested. +// - 2 if the requested libc name isn't recognised. +// - 3 if there was a usage error (it also prints an error message). + +#include +#include +#include + +#ifdef __GLIBC__ +#include +#endif + +#define False 0 +#define True 1 +typedef int Bool; + +/* Assumes the versions are x.y.z, with y and z optional. */ +static Bool matches_version(char *min_version) { + int a1=0, a2=0, a3=0, g1=0, g2=0, g3=0; // 'a' = actual; 'g' = given + const char *aversion; + + if (min_version == NULL) return True; // no version specified + + // get actual version number +#ifdef __GLIBC__ + aversion = gnu_get_libc_version(); +#else + aversion = "unknown"; +#endif + // We expect at least one number. + if (sscanf(aversion, "%d.%d.%d", &a1, &a2, &a3) < 1) return False; + + // parse given version number. + if (sscanf(min_version, "%d.%d.%d", &g1, &g2, &g3) < 1) return False; + + if (a1 > g1) return True; + if (a1 < g1) return False; + if (a2 > g2) return True; + if (a2 < g2) return False; + if (a3 >= g3) return True; + + return False; +} + +static Bool go(char* libc, char *min_version) +{ +#ifdef __GLIBC__ + if ( 0 == strcmp( libc, "glibc" ) + && matches_version( min_version )) + return True; +#endif + + return False; +} + +//--------------------------------------------------------------------------- +// main +//--------------------------------------------------------------------------- +int main(int argc, char **argv) +{ + if ( argc < 2 ) { + fprintf( stderr, "usage: libc_test []\n" ); + exit(3); // Usage error. + } + if (go( argv[1], argv[2] )) { + return 0; // Matched. + } + + if ( 0 == strcmp ( argv[1], "glibc" ) ) { + return 1; // Requested libc name known, but this isn't it. + // Or it wasn't the minimum requested version. + } + return 2; // Didn't match any known libc name. +} -- 2.47.2