From b2360a9a0abc121cd9f44c32bbdf71656efa2e83 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Fri, 28 Jan 2022 06:40:57 +0100 Subject: [PATCH] Fix process graph changes during audition Session::process_audition calls Graph::swap_process_chain() to handle any pending graph changes (notably route removal depends the graph to switch chains to drop references). However this must not change the Graph::_trigger_queue (which is refilled when processing resumes). Previously routes were added to the trigger_queue, leading to an inconsistent Graph state. When the terminal-count was reached the trigger-queue was not empty. Process threads ran after processing already completed and or concurrently with processing. A common result of that was: delayline.cc:70: virtual void ARDOUR::DelayLine::run(ARDOUR::BufferSet&, ARDOUR::samplepos_t, ARDOUR::samplepos_t, double, ARDOUR::pframes_t, bool): Assertion `lm.locked ()' failed. --- libs/ardour/ardour/graph.h | 2 +- libs/ardour/graph.cc | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libs/ardour/ardour/graph.h b/libs/ardour/ardour/graph.h index 11e35e1121..796f2bdf48 100644 --- a/libs/ardour/ardour/graph.h +++ b/libs/ardour/ardour/graph.h @@ -86,7 +86,7 @@ private: void drop_threads (); void run_one (); void main_thread (); - void prep (bool check_pending_chain = true); + void prep (); void dump (int chain) const; node_list_t _nodes_rt[2]; diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc index c6a69c50a3..aee1cdf079 100644 --- a/libs/ardour/graph.cc +++ b/libs/ardour/graph.cc @@ -232,35 +232,32 @@ Graph::swap_process_chain () /* Intended to be called Session::process_audition. * Must not be called while the graph is processing. */ - bool need_prep = false; if (_swap_mutex.trylock ()) { /* swap mutex acquired */ if (_current_chain != _pending_chain) { + DEBUG_TRACE (DEBUG::Graph, string_compose ("Graph::swap_process_chain = %1)\n", _pending_chain)); /* use new chain */ _setup_chain = _current_chain; _current_chain = _pending_chain; + printf ("Graph::swap to %d\n", _current_chain); _trigger_queue.clear (); /* ensure that all nodes can be queued */ _trigger_queue.reserve (_nodes_rt[_current_chain].size ()); g_atomic_int_set (&_trigger_queue_size, 0); _cleanup_cond.signal (); - need_prep = true; } _swap_mutex.unlock (); } - - if (need_prep) { - prep (false); - } } void -Graph::prep (bool check_pending_chain) +Graph::prep () { - if (check_pending_chain && _swap_mutex.trylock ()) { + if (_swap_mutex.trylock ()) { /* swap mutex acquired */ if (_current_chain != _pending_chain) { /* use new chain */ + DEBUG_TRACE (DEBUG::Graph, string_compose ("Graph::prep chain = %1)\n", _pending_chain)); _setup_chain = _current_chain; _current_chain = _pending_chain; /* ensure that all nodes can be queued */ @@ -281,6 +278,7 @@ Graph::prep (bool check_pending_chain) _graph_empty = false; } + assert (g_atomic_uint_get (&_trigger_queue_size) == 0); assert (_graph_empty != (_n_terminal_nodes[chain] > 0)); g_atomic_int_set (&_terminal_refcnt, _n_terminal_nodes[chain]); @@ -360,7 +358,7 @@ Graph::rechain (boost::shared_ptr routelist, GraphEdges const& edges) Glib::Threads::Mutex::Lock ls (_swap_mutex); int chain = _setup_chain; - DEBUG_TRACE (DEBUG::Graph, string_compose ("============== setup %1\n", chain)); + DEBUG_TRACE (DEBUG::Graph, string_compose ("============== setup %1 (current = %2 pending = %3) thread %4\n", chain, _current_chain, _pending_chain, pthread_name())); /* This will become the number of nodes that do not feed any other node; * once we have processed this number of those nodes, we have finished.