[AC21.5] Cleaning out old work #4: Don't exit on Mac window deletion

"Stephen J. Turnbull" <[email protected]> Mon, 4 Jan 2016 23:13:24 +0900
Newsgroups gmane.emacs.xemacs.patches
Message-ID <[email protected]>
APPROVE COMMIT 21.5

I'm surprised nobody else has reported this, but I have consistently
experience an unwanted exit when using the XQuartz window manager to
close one (of several) frames on Mac OS X.  For some reason the X I/O
error handler gets called with a "success" status (ie, 0).  I've run
with this patch for quite some time with no apparent problems.

diff -U0 -r aa31767a919f -r 0fb5bba709ed src/ChangeLog
--- a/src/ChangeLog	Thu Jan 01 16:27:23 2015 -0500
+++ b/src/ChangeLog	Mon Jan 04 15:07:49 2016 +0900
@@ -0,0 +1,15 @@
+2014-06-19  Stephen J. Turnbull  <[email protected]>
+
+	* device-x.c (x_IO_error_handler):  Check errno for a real error.
+
+	On Mac OS X 10.9 "Mavericks" and 10.10 "Yosemite", x_IO_error_handler
+	gets triggered by Cmd-W or clicking on the WM's close button:
+
+	 xemacs: Fatal I/O Error 0 (Undefined error: 0) on display connection \
+	 "/tmp/launch-HpN0rX/org.macosforge.xquartz:0.0"
+	 after 3746329 requests (3746329 known processed) \
+	with 0 events remaining.
+
+	This is inappropriate because there are other frames open on the
+	device.
+
diff -r aa31767a919f -r 0fb5bba709ed src/device-x.c
--- a/src/device-x.c	Thu Jan 01 16:27:23 2015 -0500
+++ b/src/device-x.c	Mon Jan 04 15:07:49 2016 +0900
@@ -1202,6 +1202,11 @@
 x_IO_error_handler (Display *disp)
 {
   /* This function can GC */
+  /* I'd like to just check for errno == 0 here and return, but that's
+     too risky.  Returning from an X error handler gives X the chance to
+     abort you.
+     A "goto back_to_toplevel" could be used, but on second thought I
+     decided it was a good idea to get the warning for now. */
   Lisp_Object dev;
   struct device *d = get_device_from_display_1 (disp);
 
@@ -1211,7 +1216,9 @@
   assert (d != NULL);
   dev = wrap_device (d);
 
-  if (NILP (find_nonminibuffer_frame_not_on_device (dev)))
+  /* The test against 0 is a hack for Mac OS X 10.9 and 10.10, which
+     invoke this handler on successful deletion of a window. */
+  if (errno != 0 && NILP (find_nonminibuffer_frame_not_on_device (dev)))
     {
       int depth = begin_dont_check_for_quit ();
       /* We're going down. */
@@ -1246,8 +1253,10 @@
 
   /* According to X specs, we should not return from this function, or
      Xlib might just decide to exit().  So we mark the offending
-     console for deletion and throw to top level.  */
-  if (d)
+     console for deletion and throw to top level.
+     The test against 0 is a hack for Mac OS X 10.9 and 10.10, which
+     invoke this handler on successful deletion of a window. */
+  if (errno != 0 && d)
     {
       enqueue_magic_eval_event (io_error_delete_device, dev);
       DEVICE_X_BEING_DELETED (d) = 1;