Re: [Boost-bugs] [Boost C++ Libraries] #8306: named mutex does not unlock as expected

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