BIND 10 #2198: make sure InterprocessSyncLocker is thread safe
BIND 10 Development
do-not-reply at isc.org
Thu Oct 11 03:15:22 UTC 2012
#2198: make sure InterprocessSyncLocker is thread safe
-------------------------------------+-------------------------------------
Reporter: | Owner: vorner
jinmei | Status: reviewing
Type: | Milestone:
defect | Sprint-20121023
Priority: | Resolution:
medium | Sensitive: 0
Component: | Sub-Project: Core
logging | Estimated Difficulty: 5
Keywords: | Total Hours: 0
Defect Severity: N/A |
Feature Depending on Ticket: |
Add Hours to Ticket: 0 |
Internal?: 0 |
-------------------------------------+-------------------------------------
Changes (by muks):
* owner: muks => vorner
Comment:
Hi Michal
Replying to [comment:13 vorner]:
> Hello
>
> First of all, it doesn't compile for me on a clean build ‒ the
directories need
> some reordering. Please, try a clean build and see.
Thanks for catching this. I've updated the dependencies and order of
build. It should build properly now.
> Replying to [comment:12 muks]:
> > `Mutex::tryLock()` has been added (a requirement for our `tryLock()`)
and `Mutex::lock()` and `Mutex::unlock()` were made public.
`Mutex::tryLock()` has to be public anyway. The way we use a
`Mutex::Locker`, it doesn't add benefit to dynamically allocate it (so it
lives when it runs out of scope) when we can call the same methods on
`Mutex` directly and the lock goes when it is destroyed.
>
> I'm not really happy about that. With this, we'll see stuff like this to
appear in some time:
>
> {{{#!c++
> Locker locker(mutex);
> ...
> ...
> // Unlock for a short while
> mutex.unlock();
> doSomething();
> mutex.lock();
> ...
> ...
> }}}
>
> This would be very bad if doSomething() threw.
If the code were written like this, then true. This is why the API doc
comment was added asking users of `Mutex` to consider using
`Mutex::Locker` where applicable. But where it doesn't fit in naturally,
allowing `lock()` and `unlock()` methods is not bad.
> Also, the tryLock ‒ I guess it is needed somewhere and not provided for
> completeness? Because I don't see the need for it and it seems to be
used in
> tests only.
It's required to test that the other methods work properly for a file
lock. Also because this is a interprocess synchronization object (not just
for logger), `tryLock()` is a reasonable operation to provide.
> Also, with the dynamic allocation and use of some kind of scoped_ptr,
you could get rid of the try-catch block here:
> {{{#!c++
> // First grab the thread lock...
> mutex_->lock();
>
> // ... then the file lock.
> try {
> if (do_lock(F_SETLKW, F_WRLCK)) {
> is_locked_ = true;
> return (true);
> }
> } catch (...) {
> mutex_->unlock();
> throw;
> }
>
> mutex_->unlock();
> }}}
>
> {{{#!c++
> scoped_ptr<Mutex::Locker> locker(new Locker(mutex_));
>
> if (do_lock(...)) {
> is_locked_ = true;
> locker_ = locker.release();
> return (true);
> }
>
> return (false);
> }}}
Wouldn't this involve maintaining another `locker_` member variable? Is
the current code incorrect or complicated to follow? To me the latter code
and maintaining `locker_` would be more complicated and unnatural in this
particular case.
> Also, what is the difference with lock and tryLock? While the use of
mutex is slightly different, but the call to do_lock looks exactly the
same to me.
`F_SETLKW` vs. `F_SETLK`.
> This really needs some error checking, EBUSY is not everything the
pthread_try_lock can return:
> {{{#!c++
> bool
> Mutex::tryLock() {
> assert(impl_ != NULL);
> const int result = pthread_mutex_trylock(&impl_->mutex);
> if (result != 0) {
> return (false);
> }
> ++impl_->locked_count; // Only in debug mode
> return (true);
> }
> }}}
`tryLock()` returns `false` indicating the lock operation failed. Does it
have to throw as well? I'll add it if you think it's valid.
> What is the point of the exercise with weak pointers, if the code still
relies on the fact that everything in the map is a valid pointer?
As the weak pointer maintains no direct reference, I thought it was more
understandable code. Or I am not following the question. ^^ :)
>
> Also, what is the reason behind this?
> {{{#!diff
> -#include "interprocess_sync_file.h"
> +#include <util/interprocess_sync_file.h>
> }}}
Just for consistency with the rest of the codebase.
--
Ticket URL: <http://bind10.isc.org/ticket/2198#comment:14>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list