Tag Archives: deadlock

Recursive SRW Locks

Windows Vista added new synchronization API, Slim Reader/Writer (SRW) Locks, which is a powerful alternative to critical sections. The detailed description is, as always on MSDN, and what makes it really cool is simple:

  • unlike critical sections, SRW Locks provide reader and writer access synchronization making it possible for 2 and more reader to not block one another
  • SRW Locks do not reference any resources and have size of a pointer, which is the simplest possible scenario; as a result, they don’t need a destructor and their initialization is simple zeroing of memory/variable (for which you however should use InitializeSRWLock API

Being lightweight they are efficient. To understand how at all they can work, one can imagine that a reader might be trying to InterlockedIncrement a synchronization variable. If result is positive, then it’s OK to go. Otherwise, reader should decrement it back, wait and retry. A writer, instead, does InterlockedAdd with an argument of -0×1000 and checks that result of the operation is exactly -0×1000.

This post is about a trap one cat enter into by neglecting one of the SRW lock warnings:

… so SRW locks cannot be acquired recursively. In addition, a thread that owns an SRW lock in shared mode cannot upgrade its ownership of the lock to exclusive mode.

SRW locks cannot be acquired recursively, but it is very easy to make a mistake. If you attempt to recursively acquire, you are likely to succeed, without a warning, error code, exception or assertion failure. You pass this point and you can write quite some code before you realize something is wrong.

It can be as simple as this:

Read more »

XviD video encoder and window messages from a worker thread

While encoding video, Xvid Video Encoder provides an optional status window displaying information on encoding progress.

Xvid Encoder Status Window

Since streaming typically takes place in a worker thread, with possibly no windows at all, and no message pump, the window is to be created on GUI thread and the encoder needs to synchronize progress updates with the window.

Such synchronization is a typical point where a deadlock can occur. Carelessly a window message may be sent in a blocking way so that worker thread is waiting while the message is processed on the window thread. If this sending happens at the moment of GUI thread trying to stop worker thread, a deadlock takes place. This problem often comes up when message sending takes place indirectly, e.g. being wrapped by an API call, such as SetWindowText, or as it can be seen below IsDlgButtonChecked.

In order to avoid deadlocks one should never SendMessage from a worker thread. Instead there should be a PostMessage with possibly a wait function which waits for either synchronization event (set by window) or worker thread termination request:

{
  CLock Lock(m_CriticalSection);
  m_sText = sText;
  m_SynchronizationEvent.Reset();
}
PostMessage(...);
HANDLE phObjects[] = { ThreadTerminationEvent, m_SynchronizationEvent };
const DWORD nWaitResult =  WaitForMultipleObjects(..., phObjects, ...);
if(nWaitResult == WAIT_OBJECT_0 + 1 ) // m_SynchronizationEvent
{
  CLock Lock(m_CriticalSection);
  // ...
}

Back to Xvid encoder: trying to abort encoding process, the application deadlocks. Thread checking shows worker thread state:

Xvid Video Encoder Deadlocked Thread Call Stack

That is, a described deadlock in action.

While it is already made this way letting deadlock occur, is there any workaround to avoid locking? Yes, there is. Stopping encoding, GUI thread should keep pumping messages while waiting for worker thread termination. Before closing worker thread handle, one needs to signal the thread to terminate and wait using thread handle with MsgWaitForMultipleObjects, so that messages possibly sent while terminating the thread are dispatched to target windows.