muhkuh's picture

Add option to disable calling XInitThreads under X11

Project:The Open Toolkit library
Version:1.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:confirmed
Description

OpenTK calls XInitThreads (at least) at two places:
1. ctor of OpenTK.Platform.X11.X11Factory
2. static ctor of OpenTK.Platform.X11.API

From the man page of XInitThreads:
"The XInitThreads() function initializes Xlib support for concurrent threads. This function must be the first Xlib function a multi-threaded program calls, and it must complete before any other Xlib call is made."

So the current situation is bad for two reasons.
1. XInitThreads is called twice (could be fixed easily)
2. XInitThreads might not be the first XLib call.

The second point is really the main problem here. I stubled upon this issue when writing a GTK# app that uses GLWidget to display an opengl window. GLWidget uses OpenTK to create an opengl context. Before GLWidget get's initialized and displayed a lot of XLib calls happen because this is a GTK application! In the end when GLWidget is initialized and shown OpenTK does it's XInitThreads calls.

While the program ran fine on my desktop pc is crashed in many interesting ways on my notebook. When commenting out the XInitThreads calls in OpenTK the program ran smoothly.

The only solution I can think of is removing the unconditional XInitThreads calls from OpenTK and let the user decide whether it needs multithreaded X11 or not.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

#1

Status:open» need info

Call OpenTK.Toolkit.Init() as the very first thing in your Main function to solve this issue.

Without XInitThreads, all multi-threading tests used to fail. Can you please run the multi-threading test with your modified version of the library (you can find that in Example.exe, under the OpenTK heading).

muhkuh's picture

#2

OpenTK.Toolkit.Init() (or calling XInitThreads manually) at startup fixes the crashes.

I ran the 2 multi threading examples and they worked fine on my desktop pc but that doesn't mean much. I think you are right. Multithreaded OpenGL with X11 requires XInitThreads to be called.

If you don't call XInitThreads multi threaded programs using OpenTK might fail. If you call XInitThreads on the other hand it's hard to write a piece of software like GLWidget. As a control it doesn't have any control over the main function. It can instruct it's users to call some initialization routine that calls OpenTK.Toolkit.Init() but if they forget they end up with these strange crashes that are hard to debug.

May be it would be more intuitive to not support mutli threaded X11/OpenGL by default in OpenTK. If someone needs it he has to make sure OpenTK.Toolkit.Init() is called before anything else. Otherwise an exception is thrown with a descriptive error message.

Another idea would be to add a second OpenTK.Toolkit.Init( bool doNotNeedMultiThreading). If it is called before any other OpenTK X11 stuff the XInitThreads call is omitted. So GLWidget could use this in a static ctor.

On the other hand this is a lot of work for a design catastrophe that is only present on *nix. I don't understand why XLib didn't just simply turned thread safety on by default.

muhkuh's picture

#3

Title:XInitThreads called unconditionally under *nix» Add option to disable calling XInitThreads under X11
Category:bug report» feature request
Status:need info» open

I made this a feature request. It should be possible to prevent OpenTK from calling XInitThreads under X11.

Use case:
OpenTK is not used directly but from inside a control that wants to provide an OpenGL context. So there is no reliable way to make sure OpenTK's initialization is run when main starts. This can have disastrous consequences because it might lead to XInitThreads being called (when OpenTK initializes itself implicitly) when the control gets instantiated after several X11 windows have already been created by the app. This results in obscure crashes.
Even if the documentation of the mentioned control would tell the user to call some initialization function as the first thing in main there are still cases when this is not possible. For instance when the control is loaded dynamically in some UI builder it cannot call any initialization code before main starts and the UI builder does not depend on the control at compile time.

I offer to do the implementation. Because this only an issue with X11 it should be easiest to add some kind of hint setting to tell OpenTK if it should call XInitThreads or not. The default of this hint should make OpenTK call XInitThreads as before to be compatible to existing software. What do you think?

the Fiddler's picture

#4

Version:1.0-2010-10-06» 1.x-dev
Status:open» confirmed

This can be implemented by adding a property to ToolkitOptions, i.e.:

var options = new ToolkitOptions { X11Threading = false };
Toolkit.Init(options);