Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when using OpenGL from different threads #18

Closed
crobi opened this issue May 5, 2011 · 4 comments
Closed

Crash when using OpenGL from different threads #18

crobi opened this issue May 5, 2011 · 4 comments
Labels

Comments

@crobi
Copy link

crobi commented May 5, 2011

It is not allowed to make OpenGL calls from different threads. I just happen to have a (windows) application which did it anyway and worked. Here's what happened when I used ApiTrace:

Main Application: create an OpenGL context from thread 1
Main Application: call glEnable from thread 1. Works as intended.
Plugin DLL: call glEnable from thread 2. Crash in wgltrace.cpp, inside glEnable: calling __glEnable, a NULL pointer.

So ApiTrace helped me to find the bug. However, after calling a NULL pointer, you loose the call stack (at least in the Visual Studio), so you don't know where the bug is.
If it is not too expensive, it might be therefore a good idea to check the function pointer (or thread id) before calling it.

@jrfonseca
Copy link
Member

This is the generated code from glproc.hpp:

typedef void (APIENTRY * __PFNGLENABLE)(GLenum cap);
static __PFNGLENABLE __glEnable_ptr = NULL;

static inline void APIENTRY __glEnable(GLenum cap) {
if (!__glEnable_ptr) {
__glEnable_ptr = (__PFNGLENABLE)__getPublicProcAddress("glEnable");
if (!__glEnable_ptr) {
OS::DebugMessage("error: unavailable function "glEnable"\n");
__abort();
}
}
__glEnable_ptr(cap);
}

As you can see, there is no "__glEnable" pointer, and we already check the function pointer before calling.

It looks like call stack reported by Visual Studio is totally broken & unreliable. I'd suggest building Debug build of apitrace if you haven't already and see if it helps.

Concerning multithreading in general, I haven't tested apitrace with multithreading yet. Tracing should work. but retracing will definitely not.

@crobi
Copy link
Author

crobi commented May 9, 2011

My bad, I was too fast.

The real call stack is as follows:

    1. opengl32.dll!glEnable
    1. opengl32.dll!__glEnable

Here, __glEnable_ptr is first a NULL pointer and gets (presumably correctly) loaded by getPublicProcAddress

    1. opengl32.dll!000007fef3e1b3a0()

This is inside the system opengl library. I don't see the source code here, but it crashes on the first assembler instruction after the call:

mov         ecx,dword ptr [cap] 

call        qword ptr [__glEnable_ptr]

jmp         qword ptr gs:[0D98h] 
    1. 0000000000000000()
      This is where the jump leads to, crash and no call stack available at this point.

I assume the problem is inside the system OpenGL library and you can't really do anything. The only feature could be checking the thread ID in every call, since calling OpenGL from different threads is not allowed - but that's probably not very important.

@jrfonseca
Copy link
Member

I think that calling OpenGL from different threads is allowed, provided that different OpenGL context are current on different threads. That is, you have to call wglMakeCurrent with different HGLRC contexts on every thread you wanna use OpenGL.

The reason it is jumping/calling NULL is probably because you didn't call wglMakeCurrent from thread 2.

I'm closing now, as this seems an application bug.

@crobi
Copy link
Author

crobi commented May 10, 2011

Yes, in my case it is an application bug. My point was, an appropriate check could be useful for finding these bugs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants