Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Safe" handling of a Mutex?

I'm constantly reading from a memory mapped file another process is writing to and use a mutex to synchronize this operation. In my few tests so far this works just fine, but... what if my application crashes right after acquiring the mutex and before releasing it? Is there any way to guarantee a release of the mutex, even in case of such a crash?

Also how would I handle a crash of the other process, which might not have released the mutex yet? Do I need to handle AbandonedMutexException each time I call mutex.WaitOne()?

Right now I'm doing it similar to this:

public MyState GetState()
{
    MyState state = new State();
    this._mutex.WaitOne();
    try
    {
        state.X = this._mmView.ReadSingle(0);
        state.Y = this._mmView.ReadSingle(4);
        [..]
    }
    finally
    {
        this._mutex.ReleaseMutex();
    }
    return state;
}

_mmView is a MemoryMappedViewAccessor I instantiated before. This whole method GetState() gets called each frame as part of a game loop, so about every few milliseconds.

PS: Also, is there any other obvious problem why this could fail, that I didn't already mention?

like image 312
Mario Avatar asked Feb 06 '12 23:02

Mario


People also ask

How are mutexes thread safe?

Shared mutexes and locks are an optimization for read-only pieces of multi-threaded code. It is totally safe for multiple threads to read the same variable, but std::mutex can not be locked by multiple threads simultaneously, even if those threads only want to read a value. Shared mutexes and locks allow this.

What is mutex protection?

Mutex is an abbreviation for “mutual exclusion”. Mutex variables are one of the primary means of implementing thread synchronization and for protecting shared data when multiple writes occur. A mutex variable acts like a “lock” protecting access to a shared data resource.

How do you lock a mutex?

Use pthread_mutex_lock(3THR) to lock the mutex pointed to by mutex . When pthread_mutex_lock() returns, the mutex is locked and the calling thread is the owner. If the mutex is already locked and owned by another thread, the calling thread blocks until the mutex becomes available.

What happens when mutex lock?

Mutexes are used to protect shared resources. If the mutex is already locked by another thread, the thread waits for the mutex to become available. The thread that has locked a mutex becomes its current owner and remains the owner until the same thread has unlocked it.


2 Answers

Eugen's answer is correct -- the operating system will release the mutex for you. Now think hard about what the consequences of this fact are:

  • You took out the mutex to ensure that no one would mutate state while you were reading, or read state while you were mutating. Let's suppose the latter.
  • Another application wants to read the state, so it tries to take the mutex. It is forced to wait.
  • You mutated some state and then crashed.
  • The operating system released the mutex.
  • The other application now immediately acquires the mutex, and is now effectively reading state "while" another process is mutating it. The fact that the other process is now dead and gone means that the bogus state will now last forever, and the reading process will probably itself crash and die horribly. You have just defeated the safety system provided by the mutex.

In short, you are worrying about exactly the wrong thing. You shouldn't be worried about what happens if my mutex never gets released. The worst thing that happens then is everyone waits forever, which is sad, but eventually the user will reboot the machine. You should be worried about what happens if mutex does get released because I crashed halfway through a mutation. In that scenario processes will now probably be crashing all over the place and the user's data will be permanently corrupted.

Don't get into that situation in the first place. The solution to the problem is do not crash when you have taken out a mutex for writing. If you don't write programs that crash then you don't have to worry about it, because its not going to happen. So just don't write programs that ever crash.

like image 96
Eric Lippert Avatar answered Oct 10 '22 09:10

Eric Lippert


When a process ends while owning a mutex, the OS will automatically release the mutex for you. Try this out by aquiring the mutex and then raise new WhateverException() - the other process will carry on.

The same is true for all sync primitives AFAIK

like image 20
Eugen Rieck Avatar answered Oct 10 '22 09:10

Eugen Rieck