Never Call a Handler Under a Lock

One mutex mistake can freeze an entire trading engine. Here is how Kestrel's EventBus drain avoids it.

Introduction

One Line Freezes Everything

Your event bus can freeze forever, and the bug is one innocent line.

  • Event bus
  • Mutex
  • Freeze

Handler Under a Lock

Here is the trap. A handler runs while the bus holds its lock.

  • Lock still held
  • Handler runs

Waiting on Yourself

The handler posts a new event. That needs the same lock. It waits on itself, forever.

  • post needs the lock
  • Circular wait

Lock, Then Swap

Kestrel's drain does it differently. Close the lock. Swap the entire queue into a local deque.

  • Lock closes
  • batch.swap(queue_)

Release Before Dispatch

Now open the lock. The shared queue is empty, and nobody is waiting.

  • Lock opens
  • Queue now empty

Handlers Fire Freely

Only then do handlers fire, one event at a time, from the private batch.

  • Dispatch from batch
  • Lock is open

Drain Loops Until Empty

If a handler posts, it simply locks, pushes, and leaves. Drain loops until the queue is truly empty.

  • Post is safe
  • Loop until empty

Nesting Throws Loudly

One more guard. A dispatching flag throws, EventBus drain re-entered, if anyone nests a drain.

  • dispatching_ flag
  • Throws on re-entry

Swap, Release, Dispatch

Never call a handler under a lock. Follow for more Kestrel internals.

  • Lock
  • Swap
  • Release
  • Dispatch