In fact, just #including dix-config.h above #including darwin.h in darwinKeyboard.c is enough to cause the crash.
I ran gcc with -E to see what the output of the preprocessor is, both in the crashing case and the non-crashing case. This change caught my eye:
+# 91 "../../include/dixstruct.h"
typedef struct _Client {
int index;
Mask clientAsMask;
@@ -16154,22 +16528,54 @@
int priority;
ClientState clientState;
DevUnion *devPrivates;
-# 130 "../../include/dixstruct.h"
- unsigned long replyBytesRemaining;
+
+ unsigned short xkbClientFlags;
+ unsigned short mapNotifyMask;
+ unsigned short newKeyboardNotifyMask;
+ unsigned short vMajor,vMinor;
+ KeyCode minKC,maxKC;
+
QueryMinMaxKeyCodes is failing because it's trying to dereference inputInfo.keyboard->key, which is apparently still null at that point. I added a check for null there, but then the server just crashed in some other input-initialization routine.
Coincidentally, this is why my second-most-recent stuck modifier key failed to work -- in some cases, on some machines, it would try to grab a pointer to that ->key member before that structure was initialized. I worked around that by checking earlier, but ... I think we have a general race condition here, where the dix code can end up trying to use XDarwin's input gunk before it's been initialized.
With that in mind, the following code is highly suspicious:
dix/main.c:
#ifdef XQUARTZ
/* Quartz support on Mac OS X requires that the Cocoa event loop be in
* the main thread. This allows the X server main to be called again
* from another thread. */
DarwinHandleGUI(argc, argv, envp);
#endif
DarwinHandleGui in quartz/quartzStartup.c contains this note:
/* Initially I ran the X server on the main thread, and received
events on the second thread. But now we may be using Carbon,
that needs to run on the main thread. (Otherwise, when it's
prebound, it will initialize itself on the wrong thread)
grr.. but doing that means that if the X thread gets scheduled
before the main thread when we're _not_ prebound, things fail,
so initialize by hand. */
extern void _InitHLTB(void);
_InitHLTB();
X11ControllerMain(argc, argv, server_thread, NULL);
exit(0);
So, there's been a longstanding, known race condition here -- which may be caused by this workaround for a problem which shouldn't actually exist on Leopard, since we no longer even do prebinding.
Any thoughts on how to fix this? I don't understand Carbon event handling well enough to know how to go back to the "Initially..." state.
--