Race Conditions in Emacs

Well, with all the complaints on how Emacs is not multi-threaded, one should think that we’re at least save of race conditions. Well, that’s wrong. While writing my latest application for Emacs—EIRCC, yet another IRC client—a race condition got me. Let me explain.

EIRCC receives messages from the server. If it is a private message from someone for who there is no query open, it creates a new window, initializes the user interface, and inserts the message. Simple and straightforward.

The buggy behavior showed up when someone sent me two lines very quickly (a paste). The second line got inserted into a new query window. Further lines were sent to the original window again.

The problem was that the initialization of the user interface starts an ispell process for flyspell-mode. Starting a process synchronously can get Emacs to wait, and when it waits, it can read more data from the server—calling the processing function. That’s it. Multithreading.

Oh, and as a final note, the solution was quite ugly. EIRCC now uses a global variable which controls whether new data is processed, or appended to a queue for later processing. This global variable is bound only using let. Yes, that’s right, the dynamic environment is used even for code that is run in parallel.

Yuck.