some further invalidation details:
authorRobin Gareus <robin@gareus.org>
Thu, 15 Dec 2016 17:16:03 +0000 (18:16 +0100)
committerRobin Gareus <robin@gareus.org>
Thu, 15 Dec 2016 17:19:38 +0000 (18:19 +0100)
Prevent double unref during when the EventLoop terminates:
deleting the ringbuffer deletes all requests, some of which may
contain stale invalidation

remove the buffer_map_lock, now that signals ref-count the IR.

libs/pbd/pbd/abstract_ui.cc

index 586b50aed53fd07eb1f50df8cd739e7f0072d54f..76ad5d0da409825b21393752b306cd9f9b895f8c 100644 (file)
@@ -267,6 +267,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
                                if (vec.buf[0]->invalidation) {
                                        vec.buf[0]->invalidation->unref ();
                                }
+                               vec.buf[0]->invalidation = NULL;
                                i->second->increment_read_ptr (1);
                        }
                }
@@ -418,15 +419,23 @@ AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const bo
                return;
        }
 
+       /* object destruction may race with realtime signal emission.
+        *
+        * There may be a concurrent event-loop in progress of deleting
+        * the slot-object. That's perfectly fine. But we need to mark
+        * the invalidation record itself as being used by the request.
+        *
+        * The IR needs to be kept around until the last signal using
+        * it is disconnected and then it can be deleted in the event-loop
+        * (GUI thread).
+        */
        if (invalidation) {
-               Glib::Threads::Mutex::Lock lm (request_buffer_map_lock); //  -- remove this once signal connect/disconnect uses ir->un/ref()
                if (!invalidation->valid()) {
                        DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 ignoring call-slot using functor @ %3, dead invalidation %4\n", event_loop_name(), pthread_name(), &f, invalidation));
                        return;
                }
                invalidation->ref ();
                assert (invalidation->event_loop == this);
-               invalidation->event_loop = this; // XXX is this needed,  PBD::signal::connect sets it
        }
 
        RequestObject *req = get_request (BaseUI::CallSlot);