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.