software is born like bastard children: half improvised and half compromised

Ok, a follow-up to my Xlib post from yesterday.

To more accurately describe the situation, ideally what would happen when the X connection was broken is that we’d recover gracefully and continue on our merry way. How exactly we’d reconnect to X if it ever came back wasn’t something I had gotten around to thinking about. At the very least, exiting immediately without any shutdown is unacceptable.
A lot of people emailed me with suggestions, including even our own Havoc Pennington of Havoc Pennington fame! They basically fell into one of three categories:

  1. Use an alternative X protocol implementation, like CVS Xlibs, XCB, or rolling my own minimal one.
  2. Talk to the screensaver using D-BUS.
  3. Use longjmp() to ensure that the handler method never returns to Xlib.

Unfortunately none of these is quite what I want. Here’s why:

  1. This adds a new bleeding-edge dependency to Beagle, or requires that I write a new (and certainly buggy) X protocol implementation. Beagle is just now getting to the point where it isn’t a total pain to compile, and I’d really like to keep it that way. Plus, we do use the convenience of GDK to poke at X ourselves, and using an alternate system would likely cause conflicts. If we stopped using GDK, it would require us to do all the low-level X work ourselves, which would be annoying. All together, I don’t think this solution is reasonable.
  2. This only works with gnome-screensaver. Its D-BUS interface is org.gnome.ScreenSaver, so we can pretty safely assume — at least for now — that no other screensaver program is implementing this interface. The KDE one probably doesn’t, and XScreensaver definitely doesn’t (and probably never will). Plus, our current approach works even if X simply blanks the screen. You don’t even need to be running a screensaver application. And lastly, we don’t depend on D-BUS right now, and the Mono D-BUS bindings are broken. At some point we will start using D-BUS for this sort of stuff, but things just aren’t quite ready yet.
  3. This one is definitely the nastiest and a hack. Ultimately I don’t think it’ll work because this is a Mono app, and I have no idea what kind of side effect longjmp() would cause. And while it would mean that the function wouldn’t return, it would leave around all that X apparatus in a very unclean state. This means that somehow reconnecting later is probably right out. Everybody suggested this one, though. Are there actually people out there using this to some success? I’m really interested in hearing about it.

Even before I had originally posted, it was pretty clear to me that I would just have to deal with the situation. After posting, I played around with using XSetIOErrorHandler() to begin an orderly shutdown of the Beagle daemon. Our shutdown process essentially sets a flag and signals some threads to begin shutting down, and we block while this happens. Once all the workers are finished, we stop blocking and exit the main loop. So really, it’s ideally suited to this situation. I played around with it a bit and it seems to work pretty well. We do very little cleanup after the main loop exits normally, so we don’t miss out on anything important by letting Xlib exit for us. And really, it’s probably what you want anyway: most of the time Beagle is launched as a part of your X session, you want it to shut down when you log out. This half solution allows for this, but also lets you to run it successfully without any X session at all. I checked it in last night.

One thing I noticed when I was testing this was that our IndexHelper process, which is spawned by the daemon as needed to actually do the heavy lifting of indexing, was also making an X connection and dying when the X server went away. That process uses a main loop mainly for convenience (and gtk-sharp doesn’t have a way to do purely non-UI glib main loops); it should never connect to the X server. My fix for this? Unset the DISPLAY environment variable before calling Gtk.Application.InitCheck(). Yeah, a little gross, but it works.

Comments are now closed.