I'm trying to strip some GLX window/context creation code out of a
statically-compiled binary and into a shared lib. The same code which
works fine in the static version crashes in the shared lib version on
the first call to any glX
-prefixed function. As a minimal
(non)working example, here's miniglx.cpp
:
#include <stdio.h>
#include <stdlib.h>
#include <GL/glx.h>
extern "C"{
void print_glx_version();
int main(int argc, char* argv[]);
}
void print_glx_version()
{
const char displayID[] = ":0.0";
Display *display = XOpenDisplay(displayID);
if (!display)
{
printf("Failed to open X display\n");
}
int glx_major, glx_minor;
int res = glXQueryVersion(display, &glx_major, &glx_minor);
{
printf("glX version %d.%d\n", glx_major, glx_minor);
}
}
int main(int argc, char* argv[]){
print_glx_version();
exit(0);
}
When I compile as an executable
g++ -o miniglx miniglx.cpp -lGL -lX11
and run ./miniglx
, it prints glX version 1.4
as expected.
However, when I compile as a shared lib
g++ -fPIC -shared -o libminiglx.so src/miniglx.cpp -lGL -lX11
and try to dlopen
it in another program and call
print_glx_version
, it crashes. Running in gdb
shows that the crash
occurs in the call to glXQueryVersion
and prints the message
Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7fffecdf6700 (LWP 8774)]
0x00007ffff69a6bb9 in __GI_raise (sig=sig@entry=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
The shared lib compiles and links fine, and ldd
shows it seems to
link to libGL.so
and libX11.so
:
bash$ ldd libminiglx.so
linux-vdso.so.1 => (0x00007ffff774f000)
libGL.so.1 => /usr/lib/nvidia-340/libGL.so.1 (0x00007f94c835a000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f94c8025000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f94c7c5e000)
libnvidia-tls.so.340.32 => /usr/lib/nvidia-340/tls/libnvidia-tls.so.340.32 (0x00007f94c7a5b000)
libnvidia-glcore.so.340.32 => /usr/lib/nvidia-340/libnvidia-glcore.so.340.32 (0x00007f94c4e48000)
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007f94c4c35000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f94c4a31000)
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f94c4812000)
/lib64/ld-linux-x86-64.so.2 (0x00007f94c88c4000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f94c450b000)
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f94c4307000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f94c4101000)
The one possible difference between the two situations (static vs
dynamic) is that in the static lib case I'm not dlopen
ing the lib on
the main thread (I have no control over this). Is there some problem
with doing glX window/context management stuff on other threads?
I'm on Ubuntu 14.04 LTS, with a NVIDIA Corporation GT200GL
[Quadro FX 5800] (rev a1)
GPU. The behaviour exist with both the mesa
and nvidia graphics drivers. glxinfo | head
returns
name of display: :0
display: :0 screen: 0
direct rendering: Yes
server glx vendor string: NVIDIA Corporation
server glx version string: 1.4
server glx extensions:
GLX_ARB_create_context, GLX_ARB_create_context_profile,
GLX_ARB_create_context_robustness, GLX_ARB_fbconfig_float,
GLX_ARB_multisample, GLX_EXT_buffer_age,
GLX_EXT_create_context_es2_profile, GLX_EXT_create_context_es_profile,