Subject: Re: [Boost-bugs] [Boost C++ Libraries] #8306: named mutex does not unlock as expected
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-03-18 21:10:35
#8306: named mutex does not unlock as expected
--------------------------------------------------------+-------------------
Reporter: David Hebbeker <david.hebbeker@â¦> | Owner: igaztanaga
Type: Bugs | Status: new
Milestone: To Be Determined | Component: interprocess
Version: Boost 1.52.0 | Severity: Optimization
Resolution: | Keywords: named mutex, named_mutex, semaphore, posix_named_semaphore, unlock
--------------------------------------------------------+-------------------
Comment (by steven_watanabe):
Replying to [comment:4 David Hebbeker <david.hebbeker@â¦>]:
> I expect this behaviour as I imagine that a mutex has some kind of state
machine. I hoped that there is no error / undefined state and that an
attempt to unlock in the unlocked stated would result in the unlocked
state. Just that simple.
I'm afraid that isn't how mutexes work.
> What about {{{PTHREAD_MUTEX_ERRORCHECK}}}? In that case an {{{EPERM}}}
error would be returned, which is better than undefined behaviour.
>
But note that it's still considered an error. It's just detected. Also,
in the standard, C++11 30.4.1.2: "21 The expression m.unlock() shall be
well-formed and have the following semantics. 22 Requires: The calling
thread shall own the mutex."
> > In any case, the precondition that you propose, "no other thread must
have exclusive ownership of the mutex", is basically useless. If the
current thread doesn't hold the mutex, how do you know that no other
thread holds it?
> I am not sure if I got your question: I could use try_lock() to test if
an other thread holds it.
>
If you already hold the mutex, then for a non-recursive mutex, you can't
call try_lock and for a recursive mutex, calling unlock after try_lock
will leave you exactly where you started.
Suppose that your semantics were implemented. Then consider the following
code:
{{{
Thread A:
1 - if(foo()) m.lock();
2 - m.unlock();
Thread B:
3 - m.lock();
4 - // do something
5 - m.unlock();
}}}
If B is at (4) and foo() returns false then, thread A has undefined
behavior. In order to make A correct, we'd have to make m.unlock() be a
no-op even if another thread holds m. It seems rather counterintuitive
that m.unlock() should be legal and leave the mutex locked.
> Also my workaround from above is not complete! Maybe this can be
considered, which is still not perfect:
> {{{
> if(mutex.try_lock())
> { // The mutex was free and is now locked by this thread
> mutex.unlock();
> }
> else { // The mutex is locked, try to unlock it
> mutex.unlock(); // Hopefully it is locked by this thread
> // in case an other thread holds the mutex > bad things happen
> }
> }}}
This code has exactly the same problems as plain mutex.unlock().
> The whole point is that I would like to be able to safely call unlock on
a mutex. And the behaviour should not be undefined in case it already was
unlocked.
>
> ''I am not saying, that the current implementation is defect!'' But that
it could maybe be improved by removing the restriction applied in the
precondition?
>
It's not going to happen. The bottom line is that you have to know
whether you hold a mutex in order to do anything useful with it. I don't
think that the library should go out of its way to support usage which is
very dangerous and which is not supported by any other mutex
implementation that I'm aware of.
Also, I don't even want to think about the implications of your proposed
behavior for recursive mutexes.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/8306#comment:5> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:12 UTC