From c1c43d19d4136583be9a9de0cd9ea4f74975e529 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 17 Mar 2016 14:12:47 -0400 Subject: [PATCH] Force GCC linker to see that we need pthread to work around nvidia driver bug. 1. Some Linux distributions default linker implicitly enables the as-needed linking flag. This means that your shared library or executable will only link to libraries from which they use symbols. So if you explicitly link to pthread but don't use any symbols you wont have a 'DT_NEEDED' entry for pthread. 2. NVidia libGL (driver version 352 ) uses pthread but doesn't have a DT_NEEDED entry for the library. When you run ldd or readelf on the library you won't detect any reference to the pthread library. Aside this is odd since the mesa version does explicitly link to pthread. But if you run the following command: "strings /usr/lib/nvidia-352/libGL.so.1 | grep pthread | less" You will see the following: { pthread_create pthread_self pthread_equal pthread_key_crea ... libpthread.so.0 libpthread.so pthread_create } This is very strong evidence that this library is using pthread. 3. So what does this all mean? It means that on system that use the linking flag 'as-needed', are using the nvidia driver, and don't use pthread will generate binaries that crash on launch. The only way to work around this issue is to do either: A: Specify 'no-as-needed' to the linker potentially causing over-linking and a slow down in link time B: Use a method from pthread, making the linker realize that pthread is needed. We went with method B. --- vtkm/opengl/testing/TestingWindow.h | 58 +++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/vtkm/opengl/testing/TestingWindow.h b/vtkm/opengl/testing/TestingWindow.h index 2dd7c0e14..26e7e60a3 100644 --- a/vtkm/opengl/testing/TestingWindow.h +++ b/vtkm/opengl/testing/TestingWindow.h @@ -22,6 +22,58 @@ #include #include + +#if defined(VTKM_GCC) && defined(VTKM_POSIX) && !defined(__APPLE__) +// +// 1. Some Linux distributions default linker implicitly enables the as-needed +// linking flag. This means that your shared library or executable will only +// link to libraries from which they use symbols. So if you explicitly link to +// pthread but don't use any symbols you wont have a 'DT_NEEDED' entry for +// pthread. +// +// 2. NVidia libGL (driver version 352 ) uses pthread but doesn't have +// a DT_NEEDED entry for the library. When you run ldd or readelf on the library +// you won't detect any reference to the pthread library. Aside this is odd +// since the mesa version does explicitly link to pthread. But if you run the +// following command: +// "strings /usr/lib/nvidia-352/libGL.so.1 | grep pthread | less" +// You will see the following: +// { pthread_create +// pthread_self +// pthread_equal +// pthread_key_crea +// ... +// libpthread.so.0 +// libpthread.so +// pthread_create +// } +// +// This is very strong evidence that this library is using pthread. +// +// +// 3. So what does this all mean? +// +// It means that on system that use the linking flag 'as-needed', are using +// the nvidia driver, and don't use pthread will generate binaries that crash +// on launch. The only way to work around this issue is to do either: +// +// +// A: Specify 'no-as-needed' to the linker potentially causing over-linking +// and a slow down in link time +// +// B: Use a method from pthread, making the linker realize that pthread is +// needed. +// +// +// So that is the explanation on why we have the following function which is +// never used and seems very crazy. +#include +#define VTKM_NVIDIA_PTHREAD_WORKAROUND 1 +int vtkm_force_linking_to_pthread_to_fix_nvidia_libgl_bug() + { return static_cast(pthread_self()); } +#endif + + namespace vtkm{ namespace opengl{ namespace testing{ @@ -34,6 +86,12 @@ namespace testing{ /// class TestingWindow : public vtkm::opengl::testing::WindowBase { + +#if defined(VTKM_NVIDIA_PTHREAD_WORKAROUND) + VTKM_CONT_EXPORT int vtkm_force_linking_to_pthread_to_fix_nvidia_libgl_bug() + { return vtkm_force_linking_to_pthread_to_fix_nvidia_libgl_bug(); } +#endif + public: VTKM_CONT_EXPORT TestingWindow(){};