Comment 49 for bug 86103

Revision history for this message
In , Josh Triplett (joshtriplett) wrote :

(In reply to comment #13)
> (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". :)

s/XTHREADS extension/XTHREADS extension client implementation (library or built into a program)/g, then.

> > > 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.

'no shared libraries....dynamically links to whichever "Xlib"'? You have a shared library: Xlib. You don't distribute it, so you rely on the one on the system, which means you have to match its definition of XTHREADS, or rely on other shared libraries on the system which will match it.

> 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
[from your later reply, "without 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.

Not correct. If your code builds without XTHREADS, _XReply won't even *try* to use locking functions if available. This means that if Xlib, or other extension libraries, or any other component linked into your application *does* use XTHREADS, it will not work. If you want to build without XTHREADS, you need to ship all the rest of the libraries you need without XTHREADS, either by statically linking or by shipping your own copies of shared libraries.

> > 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.

And in fact new Xlib, with Xlib/XCB, does always #define XTHREADS.

To answer your first question: the ABI of Xlib includes how you call its functions and manipulate its data structures, and the Xlibint macros define how you do that. Having XTHREADS defined or not defined changes this, and thus changes the ABI of Xlib.

> > 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().

Correct. Xlib/XCB provides an Xlib with XTHREADS defined. You may not use it from code built without XTHREADS defined. If you do so it will break. The same applies to any other Xlib built with XTHREADS. Xlib/XCB does not provide an Xlib without XTHREADS defined.

> 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.

Yes, breakage will occur if you call an XTHREADS Xlib such as Xlib/XCB using the non-XTHREADS ABI.