Segmentation fault using glGetString() with pthreads under linux
glew, glut, linux, opengl, pthreads
Solution
In order for any OpenGL call to operate properly, it requires an OpenGL context. Contexts are created using a window-system binding call (like `wglCreateContext` or similar). After creating a context, it needs to be "made current", which means associating the context with the current thread of execution. This is accomplished with another window-system specific call (like `wglMakeCurrent` for Microsoft Windows, or `glXMakeCurrent` for X Windows). GLUT abstracts all of that complexity away from you, doing all of those operations when you call `glutCreateWindow`.
Now, an important rule to know is that only a single OpenGL context can be current to a thread of execution at any one time. So, in the OP's original example, if she/he could make the context current in the Pthread they created, then the context would be lost in the main thread. The way to keep all this consistent is to only use a single context in a single thread. (It's possible to have OpenGL contexts share data, but that's neither exposed by GLUT, nor possible without using the window-system context creation calls).
In your case, it's likely that GLUT doesn't allow access to what you really need (i.e., the OpenGL context), to make it current in the other thread. You'd need to create and manage OpenGL contexts yourself.
Problem
I'm trying to load textures in a background thread to help speed up my application. The stack we are using is C/C++ on Linux, compiling with gcc. We're using OpenGL, GLUT and GLEW. We have been using libSOIL for texture loading. Ultimately, launching texture loads with libSOIL fails because it encounters a glGetString() call that causes a segfault. Trying to narrow down the problem, I wrote a very simple OpenGL application that reproduces the behavior. The below code sample shouldn't "do anything," but it also shouldn't segfault. If I knew why it did, I could in theory rework libSOIL so that it would behave in a pthreaded environment. ``` void *glPthreadTest( void* arg ) { glGetString( GL_EXTENSIONS ); //SIGSEGV return NULL; } int main( int argc, char **argv ) { glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH ); glewInit(); glGetString( GL_EXTENSIONS ); // Does not cause SIGSEGV pthread_t id; if (pthread_create( &id, NULL, glPthreadTest, (void*)NULL ) != 0) fprintf( stderr, "phtread_create glPthreadTest failed.\n" ); glutMainLoop(); return EXIT_SUCCESS; } ``` A sample stacktrace for this application from gdb looks like this: ``` #0 0x00000038492f86e9 in glGetString () from /usr/lib64/nvidia/libGL.so.1 No symbol table info available. #1 0x0000000000404425 in glPthreadTest (arg=0x0) at sf.cpp:168 No locals. #2 0x0000003148e07d15 in start_thread (arg=0x7ffff7b36700) at pthread_create.c:308 __res = <optimized out> pd = 0x7ffff7b36700 now = <optimized out> unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140737349117696, -5802871742031723458, 1, 211665686528, 140737349117696, 0, 5802854601940796478, -5829171783283899330}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}} not_first_call = 0 pagesize_m1 = <optimized out> sp = <optimized out> freesize = <optimized out> #3 0x00000031486f246d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:114 No locals. ``` You'll notice I am using the nvidia libGL implementation, but this also occurs identically with the mesa libgl that Ubuntu uses for Intel HD graphics cards. Any tips for what might be going wrong, or how to investigate further to see what's happening? Edit: Here are the #includes and the compile string for my example test: ``` #include <SOIL.h> #include <GL/glew.h> #include <GL/freeglut.h> #include <GL/freeglut_ext.h> #include <signal.h> #include <pthread.h> #include <cstdio> ``` `g++ -Wall -pedantic -I/usr/include/SOIL -O0 -ggdb -o sf sf.cpp -lSOIL -pthread -lGL -lGLU -lGLEW -lglut -lX11`