arvenil/mutex

Exception in destructor

empi89 opened this issue · 2 comments

I got exceptions like this:

Uncaught exception 'NinjaMutex\UnrecoverableMutexException' with message 'Cannot release lock in Mutex __destruct(): <mutex name> 'in /path/to/vendor/arvenil/ninja-mutex/src/NinjaMutex/Mutex.php:100
Stack trace:
#0 [internal function]: NinjaMutex\Mutex->__destruct()
#1 {main}
  thrown in /path/to/vendor/arvenil/ninja-mutex/src/NinjaMutex/Mutex.php on line 100

My code tries to deal with the exception by using unset manually to trigger the destructor and catch exception that might occur:

$mutex = $mutexFabric->get("<mutex name>");

$lock = $mutex->acquireLock();
if (!$lock) {
    throw new Exception("lock could not be acquired");
}
try {
    // CRITICAL SECTION
    $mutex->releaseLock();
    try {
        unset($mutex);
    } catch (Exception $unsetE) { }
} catch (Exception $e) {
    $mutex->releaseLock();
    try {
        unset($mutex);
    } catch (Exception $unsetE) { }
    throw $e;
}

However this does not work because the fabric stores references to the mutex and therefor the unset has no effect.
Could you introduce a method that forces the destruction of the mutex and throws catchable exceptions? Do you have an explanation on the reason of the exception? I am using memcached as backend.

This may happen when memcache becomes unavailable. Let's say you acquire lock, then shutdown memcache server, then try to release lock.

What I would do is to check return value of ->releaseLock() if you can't unlock then, sleep, and retry couple times. If you still can't unlock it because memcache is unavailable then there is nothing much you can do except notifying yourself about the issue. At this state system is broken because of a) not working memcache b) even if it came online they you will have forever locked mutex.

Sadly that's the disadvantage of memcache and redis implementation.

Ok I will git it a try, thanks for your response!