I am trying to use XEvent.type = ClientMessage to detect when a user closes a window. The attached c code is a small program to test this. It runs properly under other X servers I've tried but with XQuartz I get the following error: XIO: fatal IO error 35 (Resource temporarily unavailable) on X server "/private/tmp/com.apple.launchd.OiaccbWRVW/org.macosforge.xquartz:0" after 21 requests (16 known processed) with 0 events remaining. This problem is not new with release 2.7.8 and was also present in release 2.7.7. Not sure if it was occurring in earlier releases.
Created attachment 119156 [details] program that crashes x-server
AFAICT, there is no crash here. Your title and the title of your attachment seem to indicate that this crashes the x server, but I don't see any such crash.
Process 19612 stopped * thread #1: tid = 0x1fe4a1, function: exit , stop reason = breakpoint 3.2 frame #0: 0x00007fff9685f740 libsystem_c.dylib`exit(status=1) + 8 at exit.c:66 [opt] (lldb) bt * thread #1: tid = 0x1fe4a1, function: exit , stop reason = breakpoint 3.2 * frame #0: 0x00007fff9685f740 libsystem_c.dylib`exit(status=1) + 8 at exit.c:66 [opt] frame #1: 0x000000010008fbac libX11.6.dylib`_XDefaultIOError(dpy=0x000062100001cd88) + 316 at XlibInt.c:1258 [opt] frame #2: 0x000000010008ac8b libX11.6.dylib`_XIOError(dpy=0x000062100001cd00) + 251 at XlibInt.c:1464 [opt] frame #3: 0x0000000100084cfe libX11.6.dylib`_XReadEvents(dpy=<unavailable>) + 1566 at xcb_io.c:414 [opt] frame #4: 0x000000010004b4cd libX11.6.dylib`XNextEvent(dpy=0x000062100001cd00, event=<unavailable>) + 173 at NextEvent.c:50 [opt] frame #5: 0x0000000100000c42 crashit`event_loop + 98
Why is EAGAIN a fatal IO Error?
xcb_generic_event_t *event; dpy->xcb->event_waiter = 1; UnlockDisplay(dpy); event = xcb_wait_for_event(dpy->xcb->connection); /* It appears that classic Xlib respected user * locks when waking up after waiting for * events. However, if this thread did not have * any user locks, and another thread takes a * user lock and tries to read events, then we'd * deadlock. So we'll choose to let the thread * that got in first consume events, despite the * later thread's user locks. */ InternalLockDisplay(dpy, /* ignore user locks */ 1); dpy->xcb->event_waiter = 0; ConditionBroadcast(dpy, dpy->xcb->event_notify); if(!event) _XIOError(dpy); // Here's where we're bailing. So xcb_wait_for_event() is returning NULL.
If I keep retrying, xcb_wait_for_event eventually errs with ETIMEDOUT instead... hmm...
_xcb_conn_wait is returning false in here: while(!(ret = get_event(c))) if(!_xcb_conn_wait(c, &c->in.event_cond, 0, 0)) break; FWIW, this is true for both the poll and select codepaths. Need to dig into this more later.
Could you try moving the code that sets up WM_PROTOCOLS / WM_DELETE_WINDOW from event_loop() into create_window() (*before* the call to XMapWindow())? (No, I do not have a Mac where I could test this myself)
Looks like the WM is calling XKillClient(): (lldb) bt * thread #3: tid = 0x20aab8, function: CloseDownConnection , stop reason = breakpoint 5.1 * frame #0: 0x0000000101f44780 X11.bin`CloseDownConnection frame #1: 0x0000000101e1f804 X11.bin`CloseDownClient + 484 frame #2: 0x0000000101e3a84a X11.bin`ProcKillClient + 314 frame #3: 0x0000000101e1ebf4 X11.bin`Dispatch + 1172 And digging into quartz-wm's code, we see: - (void) do_close:(Time)timestamp { TRACE (); if (_does_wm_delete_window) { XEvent e; e.xclient.type = ClientMessage; e.xclient.window = _id; e.xclient.message_type = atoms.wm_protocols; e.xclient.format = 32; e.xclient.data.l[0] = atoms.wm_delete_window; e.xclient.data.l[1] = timestamp; XSendEvent (x_dpy, _id, False, 0, &e); } else { XKillClient (x_dpy, _id); } }
Uli, yep, moving the XSetWMProtocols() ahead of the XMapWindow() causes this to behave as expected. So now I just need to figure out what the correct behavior is here. My ICCCM is a bit rusty, but this is wither a bug in the WM or in the test app.
https://github.com/XQuartz/quartz-wm/commit/b952d8a649fb2fb8ecfd2157af1080359ef4ad84 Should be in XQuartz 2.7.10_beta2 (not yet released).
"§ 4.1.2.7. WM_PROTOCOLS Property" doesn't talk about changes while "§ 4.1.2. Client Properties" says "The window manager will examine the contents of these properties when the window makes the transition from the Withdrawn state and will monitor some properties for changes while the window is in the Iconic or Normal state." "Some properties" is quite vague, but apparently (since this works on Linux), most(?) WMs there do. Thanks for fixing this in XQuartz.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.