ReleaseMutex : Object synchronization method was called from an unsynchronized block of code

Igor Malin picture Igor Malin · Dec 8, 2014 · Viewed 8k times · Source

I have this pretty straightforward piece of code that very rarely throws "System.ApplicationException : Object synchronization method was called from an unsynchronized block of code." when ReleaseMutex() is called.

I logically analyzed the flow of the method and just cannot understand how/why this could happen. To my understanding, the ownership of mutex is guaranteed in this case:

    readonly string mutexKey;

    public Logger(string dbServer, string dbName)
    {
        this.mutexKey = ServiceManagerHelper.GetServiceName(dbServer, dbName);
    }

    private void Log(LogType type, string message, Exception ex)
    {
        using (var mutex = new Mutex(false, mutexKey))
        {
            bool acquiredMutex;
            try
            {
                acquiredMutex = mutex.WaitOne(TimeSpan.FromSeconds(5));
            }
            catch (AbandonedMutexException)
            {
                acquiredMutex = true;
            }

            if (acquiredMutex)
            {
                try
                {

                    // some application code here

                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            }
        }
    }

Answer

Hans Passant picture Hans Passant · Dec 8, 2014
        catch (AbandonedMutexException)
        {
            acquiredMutex = true;
        }

This is a very serious bug in your code. Catching an AbandonedMutexException is never correct, it is a very serious mishap. Another thread acquired the mutex but terminated without calling ReleaseMutex(). You've irrecoverably lost synchronization and the mutex is no longer usable.

You were sort of lucky by making a mistake and assuming that you acquired the mutex anyway. You didn't. The ReleaseMutex() call will now bomb with the exception you quoted.

You cannot recover from this mishap, other than by terminating the program (the wise choice) or by disabling logging completely so the mutex will never be used again. Make the wise choice by removing the catch clause. Discovering the true source of the problem, that thread that crashed and didn't call ReleaseMutex(), is out of context for this question, there are no hints. You've been ignoring this problem, papered it over by catching AME, you can't ignore it.