Monday, August 24, 2009

Getting Emacs 23.1 --daemon to play nice on Mac OS X

I've been a hard core GNU Emacs junky for nearly as long as I've been using computers, and definitely as long as I've been programming. To get my Emacs fix on Mac OS X, I've been using Aquamacs, and while I think they do a great job in general, I don't think I'm really their target audience. I'm not really looking to have a more Mac-like experience in Emacs, I just want an Emacs experience on my Mac. I was very excited to find that the GNU Emacs folks were finally main-lining the NextStep/OpenStep/Cocoa support with version 23. I was also very interested in --daemon mode, as I do have a fair amount of elisp that gets executed on startup. Unfortunately, all did not work perfectly on Mac OS X with 23.1. While the the first connection using emacsclient worked fine, after disconnecting and reconnecting, the font in the modeline would be garbled, and after disconnecting the second time, Emacs would crash. Console.app reported the stack trace each time as similar to:
Thread 0 Crashed:
0   libSystem.B.dylib              0x90071e42 __kill + 10
1   libSystem.B.dylib              0x900e423a raise + 26
2   libSystem.B.dylib              0x900f0679 abort + 73
3   org.gnu.Emacs                  0x00177985 ns_term_shutdown + 117 (nsterm.m:4015)
4   org.gnu.Emacs                  0x0009cf3f fatal_error_signal + 399 (emacs.c:389)
5   libSystem.B.dylib              0x900702bb _sigtramp + 43
6   ???                            0xffffffff 0 + 4294967295
7   libSystem.B.dylib              0x900e423a raise + 26
8   libSystem.B.dylib              0x900f0679 abort + 73
9   org.gnu.Emacs                  0x001262de font_clear_cache + 366 (font.c:2708)
10  org.gnu.Emacs                  0x00126b3b font_update_drivers + 731 (font.c:2653)
11  org.gnu.Emacs                  0x000116ba delete_frame + 442 (frame.c:1466)
Checking font.c:2708, I found:
font_assert (font && driver == font->driver);
I believed (and Wikipedia confirmed) that == binds tighter than &&, so I applied the following patch:
--- emacs-23.1/src/font.c 2009-07-28 09:51:20.000000000 -0500
+++ emacs-23.1-modified/src/font.c 2009-08-24 08:15:31.000000000 -0500
@@ -2705,7 +2705,7 @@
 
         if (! NILP (AREF (val, FONT_TYPE_INDEX)))
    {
-     font_assert (font && driver == font->driver);
+     font_assert (font && (driver == font->driver));
      driver->close (f, font);
      num_fonts--;
    }
That does indeed get me a correct modeline font on the second connection from emacsclient, and the second disconnect appears to work as well, but on the third connect, Emacs is still crashing. Just with a slightly different stack trace now:
Thread 0 Crashed:
0   libSystem.B.dylib              0x90071e42 __kill + 10
1   org.gnu.Emacs                  0x0009ceea fatal_error_signal + 314 (emacs.c:404)
2   libSystem.B.dylib              0x900702bb _sigtramp + 43
3   ???                            0xffffffff 0 + 4294967295
4   libSystem.B.dylib              0x900e423a raise + 26
5   libSystem.B.dylib              0x900f0679 abort + 73
6   org.gnu.Emacs                  0x00177985 ns_term_shutdown + 117 (nsterm.m:4015)
7   org.gnu.Emacs                  0x0009cf3f fatal_error_signal + 399 (emacs.c:389)
8   libSystem.B.dylib              0x900702bb _sigtramp + 43
9   ???                            0xffffffff 0 + 4294967295
10  com.apple.CoreGraphics         0x96f68b3c _setWindowRegion + 382
11  com.apple.CoreGraphics         0x96f6899a CGSClearDragRegion + 75
12  com.apple.AppKit               0x90bf317d _NSClearDragRectsInWindow + 62
13  com.apple.AppKit               0x90bf2b4d -[NSFrameView _resetDragMargins] + 219
14  com.apple.AppKit               0x90b1c32f -[NSThemeFrame _resetDragMargins] + 188
15  com.apple.AppKit               0x90b22a03 -[NSTitledFrame setTitle:] + 724
16  com.apple.AppKit               0x90b22540 -[NSWindow _dosetTitle:andDefeatWrap:] + 324
17  com.apple.AppKit               0x90ea417f -[NSWindow _calcAndSetFilenameTitle] + 361
18  org.gnu.Emacs                  0x001838fc ns_set_name_as_filename + 908 (nsfns.m:667)
19  org.gnu.Emacs                  0x00035577 prepare_menu_bars + 919 (xdisp.c:9506)
20  org.gnu.Emacs                  0x000364dd redisplay_internal + 3373 (xdisp.c:11475)
21  org.gnu.Emacs                  0x00036e38 redisplay_preserve_echo_area + 56 (xdisp.c:12093)
22  org.gnu.Emacs                  0x0015b224 wait_reading_process_output + 4852 (process.c:5018)
23  org.gnu.Emacs                  0x0000ccf6 sit_for + 214 (dispnew.c:6647)
Obviously, I have more testing/work to do.

Sunday, August 16, 2009

Paraphrase of Greenspun's Tenth Rule

Recently, I was trying to convince some team members that OSGi would be a good choice for a system we're designing. After indicating the benefits, as I saw them, one person asked, "Couldn't we accomplish the same thing by doing x, y and z?" At the time, I had a rather dry counter, but it occurs to me that Greenspun's Tenth Rule can be rather accurately adapted to the current Java development landscape.
Any sufficiently complicated Java program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of OSGi.