Fixing a race condition in yesod development server

April 28, 2017

In our work place, we use yesod as development server for our web application. The yesod executable has two modes of operations:

The way it works is this:

All the threads running above is synchronized properly via usage of STM. But there was a race condition in the code which always made the development server in compile mode. After lot of instrumentation, I found out that the reason behind that was this piece of code:

The Stack build process was emitting out lines even after the build was successful which again lead to overwriting of the port variable with -1. This lead it to compile mode again. Pressing Return key and re-building it again made the entire thing work but that was something I have to guess every now and then.

Solution

My initial proposed solution was to simply call the above function only when ExitFailure is emitted. But unfortunately that simple solution won’t work in all cases. After lot of tinkering, I came up with an MVar based solution which worked good enough:

The main idea is to make the port invalid during the start of the Stack build process and then don’t do any further writing on the TVar variable. When the Stack build process completes, I again make sure that it has the ability to write to the TVar variable. The ability to when to write to the TVar is controlled via the locking primitive of MVar (BuildOutput).

After a series of iteration with Michael, we changed it to a complete STM based solution:

I merged the PR yesterday. Be ready to have a race free experience in yesod devel! :-)