Scoped locking and exceptions

September 11, 2010

If you’re using the scoped mutex from the previous post how do you guarantee that an exception won’t leave the mutex locked?

One of the features of C++ is when exceptions are thrown objects on the stack are destroyed. Since the destructor of the scoped mutex controller unlocks the mutex then we’re guaranteed that the mutex will not remain locked if an exception is thrown.

Just to be rigorous lets make sure this works. Here’s a very short program to lock and unlock the mutex normally, then try throwing an exception while it’s locked:

int main( int argc, char** argv )
{
 Mutex TestMutex;

 // normal operation
 {
 Access a(TestMutex);
 std::cout << "Test 1\n";
 }
 // with an exception
 try
 {
 Access a(TestMutex);
 std::cout << "Test 2 start\n";
 throw std::runtime_error("fail");
 std::cout << "Test 2 stop\n";
 }
 catch(...)
 {
 std::cout << "Test 2 catch\n";
 }

 return 0;
}

The output from the program is what is expected:

Output:
locked
Test 1
unlocked
locked
Test 2 start
unlocked
Test 2 catch

Note that the mutex is unlocked BEFORE your exception executes.

One other thing worth noting is if you throw and unhandled exception that terminates the program your lock will not be released. If you’re just locking threads within the program this isn’t a problem but if you’re using this technique for managing a persistent lock then you may have a problem. I don’t see this as a big drawback since unhandled exceptions are something you shouldn’t leave in your applications anyway!