flush pending Session Events at session close
authorRobin Gareus <robin@gareus.org>
Thu, 28 Apr 2016 19:37:18 +0000 (21:37 +0200)
committerRobin Gareus <robin@gareus.org>
Thu, 28 Apr 2016 19:37:18 +0000 (21:37 +0200)
This prevents a memory leak: The session is closed.
The session-butler drops memory pool trash. The Engine keeps running.

Once the AudioEngine is taken down (sample-rate switch, or at exit),
the backend process-thread is terminated but there is no trash-can anymore.

If there are unprocessed SessionEvents, this calls
free_per_thread_pool() -> cp->parent()->add_to_trash (cp).
"parent()" in this case the trash-can the butler emptied.

libs/ardour/session.cc

index ef5ace53e8aa53384ab3ca17df698e9b6ecd9007..68c7d3957fdc8f99c5487a57031a4c505b29fb4a 100644 (file)
@@ -745,6 +745,42 @@ Session::destroy ()
        delete midi_clock;
        delete _tempo_map;
 
+       /* clear event queue, the session is gone, nobody is interested in
+        * those anymore, but they do leak memory if not removed
+        */
+       while (!immediate_events.empty ()) {
+               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+               SessionEvent *ev = immediate_events.front ();
+               DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Drop event: %1\n", enum_2_string (ev->type)));
+               immediate_events.pop_front ();
+               bool remove = true;
+               bool del = true;
+               switch (ev->type) {
+                       case SessionEvent::AutoLoop:
+                       case SessionEvent::AutoLoopDeclick:
+                       case SessionEvent::Skip:
+                       case SessionEvent::PunchIn:
+                       case SessionEvent::PunchOut:
+                       case SessionEvent::StopOnce:
+                       case SessionEvent::RangeStop:
+                       case SessionEvent::RangeLocate:
+                               remove = false;
+                               del = false;
+                               break;
+                       case SessionEvent::RealTimeOperation:
+                               process_rtop (ev);
+                               del = false;
+                       default:
+                               break;
+               }
+               if (remove) {
+                       del = del && !_remove_event (ev);
+               }
+               if (del) {
+                       delete ev;
+               }
+       }
+
        DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
 
 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS