boostorg / interprocess

Boost.org interprocess module
http://boost.org/libs/interprocess
132 stars 117 forks source link

In case posix_mutex::lock() detects EOWNERDEAD the exception should throw lock_exception(owner_dead_error) #187

Open wechmarer opened 1 year ago

wechmarer commented 1 year ago

In boost/interprocess/sync/posix/mutex.hpp, line 105ff the error handling depends on return value of pthread_mutex_lock(&m_mut). But regardless of whether the define BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES is set the lock_exception() throws the same reason for every case. Current: The thrown error_code_t is always not_recoverable Expected: In case of EOWNERDEAD the thrown error code should be owner_dead_error to allow the application to react accordingly

igaztanaga commented 1 year ago

If owner_dead_error is thrown, the mutex remains locked unlike any other case that throws, which breaks mutex' class invariants. EOWNERDEAD does not match with C++ mutex semantics.

wechmarer commented 1 year ago

The exception shall still be thrown after unlock of mutex. I wrote a sample using the changed code and the behaviour is as expected. In case the other process died and did not unlock the mutex the return value of pthread_mutex_trylock is:

Therefor the lock_exception should return the expected values.

Patch:

--- boost/interprocess/sync/posix/mutex.hpp.old 2022-11-18 12:29:14.884655008 +0100
+++ boost/interprocess/sync/posix/mutex.hpp     2022-11-18 12:32:07.024655318 +0100
@@ -109,7 +109,7 @@
       //corrupted, so be safe and mark the mutex as not recoverable
       //so applications can act accordingly.
       pthread_mutex_unlock(&m_mut);
-      throw lock_exception(not_recoverable);
+      throw lock_exception(owner_dead_error);
    }
    else if (res == ENOTRECOVERABLE)
       throw lock_exception(not_recoverable);
@@ -128,7 +128,7 @@
       //corrupted, so be safe and mark the mutex as not recoverable
       //so applications can act accordingly.
       pthread_mutex_unlock(&m_mut);
-      throw lock_exception(not_recoverable);
+      throw lock_exception(owner_dead_error);
    }
    else if (res == ENOTRECOVERABLE)
       throw lock_exception(not_recoverable);
@@ -156,7 +156,7 @@
       //corrupted, so be safe and mark the mutex as not recoverable
       //so applications can act accordingly.
       pthread_mutex_unlock(&m_mut);
-      throw lock_exception(not_recoverable);
+      throw lock_exception(owner_dead_error);
    }
    else if (res == ENOTRECOVERABLE)
       throw lock_exception(not_recoverable);