Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Segmentation fault using glGetString() with pthreads under linux

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

like image 945
John Snow Avatar asked Jan 15 '23 02:01

John Snow


1 Answers

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.

like image 86
radical7 Avatar answered Jan 16 '23 21:01

radical7