Comment 47 for bug 86103

Revision history for this message
In , Wez (wez) wrote :

(In reply to comment #12)
> (In reply to comment #11)
> 'Extensions' aren't thread-aware. They're just a bit of wire protocol and some
> code on the server which processes client requests. The server obviously has
> no way to know if a client's using threads, and doesn't care.

Yes. That's the point I was making, in response to Josh talking about "XTHREADS extensions". :)

> > The situation I'm describing is an application which can use a particular X
> > extension if present, and which has the code to do that built-in - it's not
> > loading a library from the host system in order to access the extension, it's
> > doing it itself via the installed Xlib. Even if it were to use a dynamic
> > library to access the extension, how is the library-builder to know whether the
> > particular Xlib installed on that host system is thread-capable or not?
> The solution is brutally simple: _share_ shared libraries. You're attempting
> to solve a distributor's problem as an ISV, and it's not working. If you want
> to distribute X client libraries, distribute Xlib and all your extension
> libraries. Don't just do half of it and be surprised when it doesn't work.

There are no shared libraries involved in the system I'm describing, nor am I distributing any. I'm talking about a single-binary, single-threaded application, which dynamically links to whichever "Xlib" is installed, whether that be Xlib or XCB, XTHREAD-ed or not.

The application has a little code in it to talk to a particular X extension via the installed "Xlib". With Xlib, this works fine whether Xlib is XTHREAD-ed or not - the extension client-side code in the application is built with XTHREADS and so does not attempt to call any locking functions. Because the application never calls XInitThreads(), Xlib doesn't create locking structures for displays, which routines like _XReply() assume means that locking isn't required.

> Because building with XTHREADS or not determines how the ABI is managed.

Can you give an example of what you mean by that? An admittedly brief glance at Xlib suggests that XTHREADS-controlled APIs such as LockDisplay() boil down to a check for locking structures followed by a per-display lock-function call, and that those structures default to null, even for non-XTHREADS builds, and are filled out only when XInitThreads() succeeds. If that were true, it would always be safe to build an extension library with XTHREADS defined, incurring only the minor performance hit of a potentially unnecessary pointer test each Lock/UnlockDisplay(), in return for compatibility with both XTHREADS & non-XTHREADS Xlib/XCB.

> I
> don't know anyone who builds without XTHREADS support these days. If your
> concern is about old systems, then, well, they're immutable, and we can't
> exactly just disable threads for all systems.
> So, it comes down to this: if you really want to support ancient systems,
> distribute Xlib and all your extension libraries. If you don't, then build
> your libraries with XTHREADS support, as everyone builds Xlib with XTHREADS.
> Everyone wins.
> We can't fix Xlib's API/ABI (both are set in stone for obvious reasons), nor
> can we do anything about the inadequacies of various distributions or systems.
> If you want to patch these up yourself, please feel free, but don't be
> surprised if it all falls apart.
> Our position is that this bug is NOTOURBUG. If you would like to fix this once
> and for all, please investigate XCB. Thanks.

The problem appears to be that XCB's locking design assumes that calling code will always call the display's "Xlib" lock & unlock functions if they are present, regardless of whether the application had previously called XInitThreads().

In the case that we're seeing the application, which is single-threaded & which includes a small amount of code to access a particular extension, built without XTHREADS, hits an assertion failure in XCB when _XReply() attempts to unlock the display's XCB lock. The assertion failure occurs because of the decision to lock & unlock XCB in _XCBLockDisplay() & _XCBUnlockDisplay() regardless of whether XInitThreads() was called - in this case the application has no threads & the code it contains for accessing the extension won't call through to LockDisplay()/UnlockDisplay(), so XCB won't see those & hook them appropriately, so when _XReply() is called & [effectively] calls UnlockDisplay(), things are in the wrong state.

From what I can tell, it should _always_ be safe to build client-side code, against any kind of "Xlib", with XTHREADS defined. In the case that Xlib is used without XInitThreads() being called, or that Xlib is XTHREADS-less, LockDisplay() & UnlockDisplay() will check for the presence of the lock functions & find them to be null. In the case that "Xlib" is XCB, or XInitThreads() is called with an XTHREADS-ed Xlib, it'll find lock & unlock functions in the display structure & call them.

Does that sound plausible?

Thanks!