Skip to content

Commit

Permalink
mutex 'er up
Browse files Browse the repository at this point in the history
Some overzealous locking to track down RequestObject related crashes.

bc0fa4d wrongly locked the current event loop's
request_invalidation_lock instead of the invalidation's list lock.

Also Abstract UI is able to delete requests concurrently with with
EventLoop invalidation.
e.g. PortManager::PortRegisteredOrUnregistered  and GlobalPortMatrixWindow
so the lock needs to be exposed.

If this solves various issues, mutexes should to be consolidated
(request_buffer_map_lock + request_invalidation_lock) and be chosen
such that there is as little contention as possible.
  • Loading branch information
x42 committed Dec 13, 2016
1 parent 176625d commit fa07233
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 6 deletions.
3 changes: 2 additions & 1 deletion libs/pbd/event_loop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ EventLoop::set_event_loop_for_thread (EventLoop* loop)
void*
EventLoop::invalidate_request (void* data)
{
InvalidationRecord* ir = (InvalidationRecord*) data;
InvalidationRecord* ir = (InvalidationRecord*) data;

/* Some of the requests queued with an EventLoop may involve functors
* that make method calls to objects whose lifetime is shorter
Expand Down Expand Up @@ -88,6 +88,7 @@ EventLoop::invalidate_request (void* data)

if (ir->event_loop) {
Glib::Threads::Mutex::Lock lm (ir->event_loop->slot_invalidation_mutex());
Glib::Threads::Mutex::Lock lr (ir->event_loop->request_invalidation_mutex());
for (list<BaseRequestObject*>::iterator i = ir->requests.begin(); i != ir->requests.end(); ++i) {
(*i)->valid = false;
(*i)->invalidation = 0;
Expand Down
7 changes: 5 additions & 2 deletions libs/pbd/pbd/abstract_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ AbstractUI<RequestObject>::handle_ui_requests ()
request_buffer_map_lock.lock ();
if (vec.buf[0]->invalidation) {
DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: removing invalidation record for that request\n", event_loop_name()));
Glib::Threads::Mutex::Lock lm (request_invalidation_lock);
assert (vec.buf[0]->invalidation->event_loop);
Glib::Threads::Mutex::Lock lm (vec.buf[0]->invalidation->event_loop->request_invalidation_mutex());
if (!(*i).second->dead) {
vec.buf[0]->invalidation->requests.remove (vec.buf[0]);
}
Expand All @@ -257,6 +258,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()

/* clean up any dead request buffers (their thread has exited) */

Glib::Threads::Mutex::Lock lr (request_invalidation_lock);
for (i = request_buffers.begin(); i != request_buffers.end(); ) {
if ((*i).second->dead) {
DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 deleting dead per-thread request buffer for %3 @ %4\n",
Expand Down Expand Up @@ -304,8 +306,9 @@ AbstractUI<RequestObject>::handle_ui_requests ()
*/

if (req->invalidation) {
Glib::Threads::Mutex::Lock lm (request_invalidation_lock);
DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", event_loop_name(), pthread_name()));
assert (req->invalidation->event_loop && req->invalidation->event_loop != this);
Glib::Threads::Mutex::Lock lm (req->invalidation->event_loop->request_invalidation_mutex());

/* after this call, if the object referenced by the
* invalidation record is deleted, it will no longer
Expand Down
3 changes: 2 additions & 1 deletion libs/pbd/pbd/abstract_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ class ABSTRACT_UI_API AbstractUI : public BaseUI

void register_thread (pthread_t, std::string, uint32_t num_requests);
void call_slot (EventLoop::InvalidationRecord*, const boost::function<void()>&);
Glib::Threads::Mutex& slot_invalidation_mutex() { return request_buffer_map_lock; }
Glib::Threads::Mutex& slot_invalidation_mutex() { return request_buffer_map_lock; }
Glib::Threads::Mutex& request_invalidation_mutex() { return request_invalidation_lock; }

Glib::Threads::Mutex request_buffer_map_lock;
Glib::Threads::Mutex request_invalidation_lock;
Expand Down
5 changes: 3 additions & 2 deletions libs/pbd/pbd/event_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ class LIBPBD_API EventLoop
};

virtual void call_slot (InvalidationRecord*, const boost::function<void()>&) = 0;
virtual Glib::Threads::Mutex& slot_invalidation_mutex() = 0;
virtual Glib::Threads::Mutex& slot_invalidation_mutex() = 0;
virtual Glib::Threads::Mutex& request_invalidation_mutex() = 0;

std::string event_loop_name() const { return _name; }
std::string event_loop_name() const { return _name; }

static EventLoop* get_event_loop_for_thread();
static void set_event_loop_for_thread (EventLoop* ui);
Expand Down
2 changes: 2 additions & 0 deletions session_utils/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,12 @@ class MyEventLoop : public sigc::trackable, public EventLoop
}

Glib::Threads::Mutex& slot_invalidation_mutex() { return request_buffer_map_lock; }
Glib::Threads::Mutex& request_invalidation_mutex() { return request_invalidation_lock; }

private:
Glib::Threads::Thread* run_loop_thread;
Glib::Threads::Mutex request_buffer_map_lock;
Glib::Threads::Mutex request_invalidation_lock;
};

static MyEventLoop *event_loop;
Expand Down
2 changes: 2 additions & 0 deletions tools/luadevel/luasession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@ class MyEventLoop : public sigc::trackable, public EventLoop
}

Glib::Threads::Mutex& slot_invalidation_mutex () { return request_buffer_map_lock; }
Glib::Threads::Mutex& request_invalidation_mutex() { return request_invalidation_lock; }

private:
Glib::Threads::Thread* run_loop_thread;
Glib::Threads::Mutex request_buffer_map_lock;
Glib::Threads::Mutex request_invalidation_lock;
};

static MyEventLoop *event_loop = NULL;
Expand Down

0 comments on commit fa07233

Please sign in to comment.