Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Monitor.Enter throw an exception?

Can Monitor.Enter throw any exception. I am doing a code review and find that Monitor.Enter is before try block. Do you see any issues with in?

Monitor.Enter(...)
try
{
    ...
}
finally
{
    Monitor.Exit(..)
}
like image 814
palm snow Avatar asked Jan 12 '12 18:01

palm snow


2 Answers

This is the correct pattern, whether Enter() throws (can throw) or not.

Only after the call to Enter() succeeds your code is under the responsibility to call Exit().

Suppose the call to Enter() fails. Then calling the corresponding Exit() is simply incorrect, it will make matters worse. So Enter() has to be outside (before) the try block.

like image 135
Henk Holterman Avatar answered Oct 04 '22 04:10

Henk Holterman


Hans Passant's comment is of course correct. If Monitor.Enter throws before the lock is taken then you do not want the finally to run. If it throws after the lock is taken and after the try is entered, then the lock is released. (More on this later.) But if the throw happens after the lock is taken but before the try is entered, then the lock will never be cleaned up.

This is a rare but possible situation.

In C# 4 we changed the codegen of the lock statement so that the monitor enter is inside the try. This ensures that the lock is always released if something throws after the lock is taken. However, note that this might still be wrong. If something throws after the lock is taken then whatever non-atomic mutation the lock is protecting might be half-completed, and the finally block then unlocks the lock and allows access to the inconsistent state! The fundamental problem here is that you shouldn't be throwing inside a lock in the first place.

See my article about the issue for more discussion.

like image 41
Eric Lippert Avatar answered Oct 04 '22 02:10

Eric Lippert