enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / pbd / pbd / abstract_ui.cc
index e186161cf9773ed06f18727660afcbd6e08cc4fa..6f03f2554e6b257e7c37f0db74f6de73a28534ab 100644 (file)
@@ -26,7 +26,7 @@
 #include "pbd/failed_constructor.h"
 #include "pbd/debug.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 #ifdef COMPILER_MSVC
 #include <ardourext/misc.h>  // Needed for 'DECLARE_DEFAULT_COMPARISONS'. Objects in an STL container can be
@@ -54,7 +54,7 @@ cleanup_request_buffer (void* ptr)
         * a request. If the UI has finished processing requests, then
         * we will leak this buffer object.
         */
-
+       DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("thread \"%1\" exits: marking request buffer as dead @ %2\n", pthread_name(), rb));
        rb->dead = true;
 }
 
@@ -224,6 +224,19 @@ AbstractUI<RequestObject>::handle_ui_requests ()
                                        request_buffer_map_lock.unlock ();
                                        DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: valid request, calling ::do_request()\n", event_loop_name()));
                                        do_request (vec.buf[0]);
+
+                                       /* if the request was CallSlot, then we need to ensure that we reset the functor in the request, in case it
+                                        * held a shared_ptr<>. Failure to do so can lead to dangling references to objects passed to PBD::Signals.
+                                        *
+                                        * Note that this method (::handle_ui_requests()) is by definition called from the event loop thread, so
+                                        * caller_is_self() is true, which means that the execution of the functor has definitely happened after
+                                        * do_request() returns and we no longer need the functor for any reason.
+                                        */
+
+                                       if (vec.buf[0]->type == CallSlot) {
+                                               vec.buf[0]->the_slot = 0;
+                                       }
+
                                        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()));
@@ -245,10 +258,13 @@ AbstractUI<RequestObject>::handle_ui_requests ()
                if ((*i).second->dead) {
                        DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 deleting dead per-thread request buffer for %3 @ %4\n",
                                                                             event_loop_name(), pthread_name(), i->second));
-                       cerr << event_loop_name() << " noticed that a buffer was dead\n";
+                       /* remove it from the EventLoop static map of all request buffers */
+                       EventLoop::remove_request_buffer_from_map ((*i).second);
+                       /* delete it */
                        delete (*i).second;
                        RequestBufferMapIterator tmp = i;
                        ++tmp;
+                       /* remove it from this thread's list of request buffers */
                        request_buffers.erase (i);
                        i = tmp;
                } else {
@@ -428,7 +444,7 @@ AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const bo
 template<typename RequestObject> void*
 AbstractUI<RequestObject>::request_buffer_factory (uint32_t num_requests)
 {
-       RequestBuffer*  mcr = new RequestBuffer (num_requests);
+       RequestBuffer*  mcr = new RequestBuffer (num_requests); // leaks
        per_thread_request_buffer.set (mcr);
        return mcr;
 }