Deadlock Empire

This is a short writeup of a small programming game @damageboy introduced me to. The game focuses on finding and exploiting race conditions in an environment similar to .net.

Link to the game and my forked copy of the game (to make sure the link keeps working). All credit for the game goes to the original programmers, Petr Hudeček and Michal Pokorný on HackCambridge 2016.

## The game

The game is simple, you are the scheduler and can control and interleave operations across threads. The operations can be atomic, such as semaphore.Release(); or non atomic operations such as x = x +1 . The goal is to reach a non safe state for each code snippet, non safe can be removing an item from an empty queue, a dead lock, livelock, etc.

Selected levels

Confused Counter

This level is a good introduction to the fact nothing should be considered atomic unless explicitly defined this way. Confused Counter

Many programmers are used to the idea that ++x is translated to x=x+1 and some programmers who understand machine instructions understand this may be transformed to the following instruction sequence.

mov eax, [x]
add x,1
mov [x],eax

Clearly this sequence is not atomic but some programmers believe that add [x],1 is atomic!

Clearly after this introduction, we notice that given careful scheduling we can reach the following state

Confused Counter

And we will enter the if block and hit the assert.

Producer Consumer

Another good example that nothing is atomic unless explicitly mentioned as such.

Basic producer consumer

This game is based on .net objects, which are not automatically thread safe and therfore, it’s easy to to reach a state where the Queue.Count is greater than 0 but there’s no object yet inside the queue.

Barriers

In .net, Barriers function like club bouncers. They wait for a specified amount of threads to reach the barrier then let them through at once. This is obviously problematic if you don’t know the precise amount of threads you want to participate.

Barrier start

Note the barrier here waits for 2 threads and we have 3. Our goal is to reach Debug.Assert. Note that at every stage, the counter is properly handled!

Given the above, can you reverse engineer how I reached the following state?

Barrier part 2

Locking scope

The following code for the Dragon Head threads is correct except for one basic flaw, the lock should be outside the lock :)

image-20200729113644692

Why is this problematic?

image-20200729113717438

A note

This game is a cute example but no one should be writing application code that looks like this in 2020 unless they’re doing low level programming.

Reactive programming, based on callbacks and with strong control of scope have proven to be safely usably by programmers without special training.