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.
This commit is contained in:
Robert Maynard 2016-03-17 14:12:47 -04:00
parent 3b06784146
commit c1c43d19d4

@ -22,6 +22,58 @@
#include <vtkm/internal/ExportMacros.h>
#include <vtkm/opengl/testing/WindowBase.h>
#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 <pthread.h>
#define VTKM_NVIDIA_PTHREAD_WORKAROUND 1
int vtkm_force_linking_to_pthread_to_fix_nvidia_libgl_bug()
{ return static_cast<int>(pthread_self()); }
#endif
namespace vtkm{
namespace opengl{
namespace testing{
@ -34,6 +86,12 @@ namespace testing{
///
class TestingWindow : public vtkm::opengl::testing::WindowBase<TestingWindow>
{
#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(){};