OpenGLComponent + threads + multiple X displays -> freeze


#1

Hi,

I have the following problem: I’m running 3 instances of the same application on one linux machine - the machine has 6 displays connected and each instance renders 3d graphics to two displays. Those pairs of displays are addressed with one X11 port each and connected to one graphics card each. Each client is therefore connected to one of the three X ports.

So, each of the clients has one render thread. The problem is that the second or third instance I start on a machine might deadlock while trying to call makeCurrentContextActive() for the second time (first time it just fails to activate it, but returns). This only happens in the Release build (though it doesn’t happen always), and only if I’m not loading the program into GDB. I’m assuming it can’t acquire the context lock in the makeCurrentContextActive() call, but I’m not sure why, as it’s the only thread drawing into that context. For the instance or instances that succeed with the initial activation, the context is never again deactivated and everything is fine.

in the code, the problematic section looks like this:


class NodeRenderView : public OpenGLComponent, public Thread

// .....

void NodeRenderView::run()
{
	while (!threadShouldExit())
	{
		if (makeCurrentContextActive()) // on the 2nd or 3rd client, this sometimes fails to return on the second call
		{
          ScopedLock sl(getContextLock());

			// render things

		}
		else
		{
			usleep(50000);
		}
	}

        // cleanup
}

I saw that people have had tricky situations with OpenGL + threads before so I thought someone might have an idea how to solve this…

thanks in advance!


#2

Blimey, that’s quite a rig you’ve got going!

I’m afraid my experience of GL on linux is pretty shallow, even when there’s only one display involved, so will leave it to others to hopefully suggest something!


#3

Hmm, I forget - each Juce app has it’s own Display Connection? I wonder if all the apps have a connection to the same X Server, and therefore DisplayConnections to the same X server, and that’s where it goes wrong?

For a while, I had a threaded GL on Linux system where I opened my own Display connection on the same thread as the X screen context will be. That’s the ideal. A current workaround is to use juce’s connection.

That’s what I would try: make a thread, open a connection to that X screen, create the GL context and do all work using that connection. You will need to recreate a fair amount of juce code though. If it is the problem, we should make an effort to get that back into the juce base for the threaded case and/or cases where an OpenGLComponent will be used on a display other than the main one.

Bruce


#4

[quote=“Bruce Wheaton”]Hmm, I forget - each Juce app has it’s own Display Connection? I wonder if all the apps have a connection to the same X Server, and therefore DisplayConnections to the same X server, and that’s where it goes wrong?

For a while, I had a threaded GL on Linux system where I opened my own Display connection on the same thread as the X screen context will be. That’s the ideal. A current workaround is to use juce’s connection.

That’s what I would try: make a thread, open a connection to that X screen, create the GL context and do all work using that connection. You will need to recreate a fair amount of juce code though. If it is the problem, we should make an effort to get that back into the juce base for the threaded case and/or cases where an OpenGLComponent will be used on a display other than the main one.

Bruce[/quote]

Thanks for the reply!

In the meantime I discovered that it seems the problem doesn’t occur when i let the thread sleep for much longer (~ 1 second, in the else branch) if it fails initial activation - it can then activate on the second try. This works for me in the current setup, but of course I’d rather know the cause of the problem…

I had a look at the Xlib code of Juce… I can’t say I really know what’s going on there. Did I understand correctly that you think it could make all the difference if I had the XOpenDisplay() and the makeCurrentContextActive() on the same thread?


#5

[Possibly] using XOpenDisplay to make a new connection to X, on the thread, and using that for all OpenGL actions would help. It would require quite a bit of re-implementation. If you were to do it, and find it works, I would help you find a way to make it the standard way a Linux threaded openGL context works.

Bruce