Check for using correct hwloc headers and runtime
authorPaul Bauer <paul.bauer.q@gmail.com>
Wed, 27 Nov 2019 15:35:16 +0000 (16:35 +0100)
committerPaul Bauer <paul.bauer.q@gmail.com>
Fri, 13 Dec 2019 15:34:16 +0000 (16:34 +0100)
Also add assertion in the code to prevent errors from linking
against the wrong library while running.

Fixes #3200

Change-Id: Ib2f2861702e111f67c38b0c9d65ccbe4c81a0ccd

cmake/FindHwloc.cmake
docs/release-notes/2019/2019.5.rst
src/config.h.cmakein
src/gromacs/hardware/hardwaretopology.cpp

index 8bfb9cd616902398c41f9ec1ae60ffff92ea5f1e..8eda2a4c5e39f4ccee98c167e22a24f4a9f46f85 100644 (file)
@@ -1,7 +1,7 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2015,2016,2017,2018, by the GROMACS development team, led by
+# Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 # and including many others, as listed in the AUTHORS file in the
 # top-level source directory and at http://www.gromacs.org.
@@ -97,7 +97,7 @@ if(HWLOC_INCLUDE_DIRS)
                message(STATUS "Error executing hwloc-info: ${HWLOC_INFO_ERR}")
             endif()
             string(REGEX MATCH "[0-9]+.*[0-9]+" HWLOC_INFO_OUT "${HWLOC_INFO_OUT}")
-            set(HWLOC_VERSION ${HWLOC_INFO_OUT} CACHE STRING "Hwloc library version")
+            set(HWLOC_LIBRARY_VERSION ${HWLOC_INFO_OUT} CACHE STRING "Hwloc library version")
         endif()
     endif()
 
@@ -106,20 +106,35 @@ if(HWLOC_INCLUDE_DIRS)
     endif()
 
     # Parse header if cross-compiling, or if hwloc-info was not found
-    if(NOT HWLOC_VERSION)
-        # Hwloc is never installed as a framework on OS X, so this should always work.
-        file(READ "${HWLOC_INCLUDE_DIRS}/hwloc.h"
-             HEADER_CONTENTS LIMIT 16384)
-        string(REGEX REPLACE ".*#define HWLOC_API_VERSION (0[xX][0-9a-fA-F]+).*" "\\1"
-               HWLOC_API_VERSION "${HEADER_CONTENTS}")
-        string(SUBSTRING "${HWLOC_API_VERSION}" 4 2 HEX_MAJOR)
-        string(SUBSTRING "${HWLOC_API_VERSION}" 6 2 HEX_MINOR)
-        string(SUBSTRING "${HWLOC_API_VERSION}" 8 2 HEX_PATCH)
-        hex2dec(${HEX_MAJOR} DEC_MAJOR)
-        hex2dec(${HEX_MINOR} DEC_MINOR)
-        hex2dec(${HEX_PATCH} DEC_PATCH)
-        set(HWLOC_VERSION "${DEC_MAJOR}.${DEC_MINOR}.${DEC_PATCH}" CACHE STRING "Hwloc library version")
+    # Also used to check that library and header versions match
+    # HWLOC is never installed as a framework on OS X, so this should always work.
+    file(READ "${HWLOC_INCLUDE_DIRS}/hwloc.h"
+         HEADER_CONTENTS LIMIT 16384)
+    string(REGEX REPLACE ".*#define HWLOC_API_VERSION (0[xX][0-9a-fA-F]+).*" "\\1"
+           HWLOC_API_VERSION "${HEADER_CONTENTS}")
+    string(SUBSTRING "${HWLOC_API_VERSION}" 4 2 HEX_MAJOR)
+    string(SUBSTRING "${HWLOC_API_VERSION}" 6 2 HEX_MINOR)
+    string(SUBSTRING "${HWLOC_API_VERSION}" 8 2 HEX_PATCH)
+    hex2dec(${HEX_MAJOR} DEC_MAJOR)
+    hex2dec(${HEX_MINOR} DEC_MINOR)
+    hex2dec(${HEX_PATCH} DEC_PATCH)
+    set(HWLOC_HEADER_VERSION "${DEC_MAJOR}.${DEC_MINOR}.${DEC_PATCH}")
+    if (HWLOC_LIBRARY_VERSION AND HWLOC_HEADER_VERSION)
+        string(SUBSTRING "${HWLOC_LIBRARY_VERSION}" 0 1 LIBRARY_MAJOR)
+        string(SUBSTRING "${HWLOC_HEADER_VERSION}" 0 1 HEADER_MAJOR)
+        string(COMPARE EQUAL "${LIBRARY_MAJOR}" "${HEADER_MAJOR}" HWLOC_VERSION_CHECK)
+        if(NOT HWLOC_VERSION_CHECK)
+            message(FATAL_ERROR "Detected version mismatch between HWLOC headers and library. "
+            "Library version is ${HWLOC_LIBRARY_VERSION}, but header version is ${HWLOC_HEADER_VERSION}. "
+            "Make sure that you have the correct include and library directory set for HWLOC")
+        endif()
+    endif()
+    if (HWLOC_LIBRARY_VERSION)
+        set(HWLOC_VERSION ${HWLOC_LIBRARY_VERSION} CACHE STRING "HWLOC library version")
+    else()
+        set(HWLOC_VERSION ${HWLOC_HEADER_VERSION} CACHE STRING "HWLOC library version")
     endif()
+    set(GMX_HWLOC_API_VERSION ${HWLOC_API_VERSION} CACHE STRING "HWLOC API version during configuration time")
 endif()
 
 include(FindPackageHandleStandardArgs)
index 474ceb90530c17513d2dc240440267d923413330..5f2530099e43a29ab40e2421df7722c2fc8d05f3 100644 (file)
@@ -90,6 +90,15 @@ which was not clear for users.
 Fixes that affect portability
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+Check that libhwloc headers and runtime match
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+It could happen that the libhwloc headers and library detection would
+lead to a mismatch at compile or runtime that could cause cryptic
+crashes while using mdrun.
+
+:issue:`3200`
+
 Miscellaneous
 ^^^^^^^^^^^^^
 
index c685f264b5e4b23cbc7669b87e945dc1be873a54..7824bf636b4c0f117ed7079e07c035adeed7f1a9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
 /* Use the Portable Hardware Locality package (hwloc) */
 #cmakedefine01 GMX_USE_HWLOC
 
+/* Library version found for hwloc during configuration time */
+#define GMX_HWLOC_API_VERSION @GMX_HWLOC_API_VERSION@
+
 /* Can and should use nice(3) to set priority */
 #cmakedefine01 GMX_USE_NICE
 
index ae2ce7670640fd04810bf1d7d64f8975b94e1205..33c2b3ab7cb1c52a78f56881c3b7db2755a0dfcd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -161,11 +161,17 @@ parseCpuInfo(HardwareTopology::Machine *        machine,
 #endif
 
 // Preprocessor variable for if hwloc api is version 1.x.x or 2.x.x
-#if HWLOC_API_VERSION >= 0x00020000
-#    define GMX_HWLOC_API_VERSION_IS_2XX 1
-#else
-#    define GMX_HWLOC_API_VERSION_IS_2XX 0
-#endif
+#    if HWLOC_API_VERSION >= 0x00020000
+#        define GMX_HWLOC_API_VERSION_IS_2XX 1
+#        if GMX_HWLOC_API_VERSION < 0x00020000
+#            error "HWLOC library major version set during configuration is 1, but currently using version 2 headers"
+#        endif
+#    else
+#        define GMX_HWLOC_API_VERSION_IS_2XX 0
+#        if GMX_HWLOC_API_VERSION >= 0x00020000
+#            error "HWLOC library major version set during configuration is 2, but currently using version 1 headers"
+#        endif
+#    endif
 
 /*****************************************************************************
  *                                                                           *
@@ -607,9 +613,15 @@ parseHwLoc(HardwareTopology::Machine *        machine,
     }
 
     // Flags to look for io devices
-#if GMX_HWLOC_API_VERSION_IS_2XX
+#    if GMX_HWLOC_API_VERSION_IS_2XX
+    GMX_RELEASE_ASSERT(
+            (hwloc_get_api_version() >= 0x20000),
+            "Mismatch between hwloc headers and library, using v2 headers with v1 library");
     hwloc_topology_set_io_types_filter(topo, HWLOC_TYPE_FILTER_KEEP_IMPORTANT);
-#else
+#    else
+    GMX_RELEASE_ASSERT(
+            (hwloc_get_api_version() < 0x20000),
+            "Mismatch between hwloc headers and library, using v1 headers with v2 library");
     hwloc_topology_set_flags(topo, HWLOC_TOPOLOGY_FLAG_IO_DEVICES);
 #endif