Boost logo

Boost Users :

Subject: Re: [Boost-users] [boost][interprocess] upgradable_mutex is semi-recursive...
From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2009-01-22 13:01:15


Lars Hagström wrote:
> The subject is misleading, but hopefully eye-catching :-)
> I do understand that this is not an interprocess bug, but more of a
> result of how upgradeable locks work.
> But the behavior can be dangerous, as will be seen.
>
> What I've got happening is that one process locks the mutex recursively
> (sharable, of course). And this works (most of the time), since it is
> okay to lock the mutex shareably any number of times (even if it is
> within the same thread).
> But the problem occurs when a writer (in another thread) manages to get
> inbetween these lockings, when we get this sequence
>
> thread A locks mutex shareably
> thread B waits for exclusive lock
> thread A waits for sharable lock
>
> Since the upgradable mutex is written so that if there is an exclusive
> locker waiting it doesnt let any more sharable lockers in this will
> deadlock.
>
> Something that explains this could be useful in the interprocess
> documentation.

Well, upgradable::lock() has two gates, first it waits until upgradable
and exclusive owners unlock. After that it waits until all readers are
gone. Obviously, if readers are not leaving the lock you are not going
to be able to continue. This means that writers have priority over readers.

I don't mention anywhere that upgradable lock is recursive, so this is
not going to work if you use it that way. An
inteprocess_upgradable_recursive_mutex could be an option but it's not
easy to implement.

> Or, maybe the problem could be solved. I see two ways:
>
> 1. Detect recursive sharable locking, so that my thread A would always
> get an exception when trying to lock a lock that I've already got (it is
> a recipe for disaster)

That's an option but you might have infinite readers, and having a map
with thread_id/lock count is hard. But placing it in shared memory (with
no shared-memory allocators around) is nearly impossible. That's why I
chose not to detect recursiveness.

> 2. Allow recursive sharable locks. If you've got the lock it's okay to
> take it again.

I find this difficult to implement for shared memory and expensive for
intra-process (Boost.Thread) mutexes.

> Since I'm not really a fan of recursive locking (the above locking is a
> mistake, really) I think I would prefer solution 1 of these two.

> (I'm fixing my code to not be recursive now, but I thought this might be
> of interest to either Ion or anyone using boost interprocess.)

You've chosen option 3: don't use a non-recursive mutex as recursive.
Mutexes are not required to notify these errors, precisely because
sometimes is hard/expensive to detect this.

I really would like to implement option 1 or 2, but I still don't see an
easy solution. Sorry!

> Cheers
> Lars

Regards,

Ion


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net