summaryrefslogtreecommitdiff
path: root/libs/ardour/session.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2020-04-26 22:17:18 +0200
committerRobin Gareus <robin@gareus.org>2020-04-26 22:17:18 +0200
commitb0daa85bfbaa4bdbdd25f47d4d642726c37a4d38 (patch)
tree74032f6180322887298e32db9fb0f1f5df56b719 /libs/ardour/session.cc
parent31c39ed8696658a0b4d4d7dc7e4ab5880bcecd4d (diff)
Prevent race between adding ports and IO port-lookup
Diffstat (limited to 'libs/ardour/session.cc')
-rw-r--r--libs/ardour/session.cc19
1 files changed, 18 insertions, 1 deletions
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 7518285109..7f4740057d 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -6549,6 +6549,18 @@ Session::update_latency (bool playback)
reverse (r->begin(), r->end());
}
+ /* Session::new_midi_track -> Route::add_processors -> Delivery::configure_io
+ * -> IO::ensure_ports -> PortManager::register_output_port
+ * may run currently (adding many ports) while the backend
+ * already emits AudioEngine::latency_callback() for previously
+ * added ports.
+ *
+ * Route::set_public_port_latencies() -> IO::latency may try
+ * to lookup ports that don't yet exist.
+ * IO::* uses BLOCK_PROCESS_CALLBACK to prevent concurrency,
+ * so the same has to be done here to prevent a race.
+ */
+ Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
samplecnt_t latency = (*i)->set_private_port_latencies (playback);
(*i)->set_public_port_latencies (latency, playback);
@@ -6560,15 +6572,20 @@ Session::update_latency (bool playback)
* With internal backends, AudioEngine::latency_callback () -> this method
* is called from the main_process_thread (so the lock is not contended).
* However jack2 can concurrently process and reconfigure port latencies.
+ * -> keep the process-lock.
*/
- Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
/* prevent any concurrent latency updates */
Glib::Threads::Mutex::Lock lx (_update_latency_lock);
set_worst_output_latency ();
update_route_latency (true, /*apply_to_delayline*/ true);
+ /* relese before emiting signals */
+ lm.release ();
+
} else {
+ /* process lock is not needed to update worst-case latency */
+ lm.release ();
Glib::Threads::Mutex::Lock lx (_update_latency_lock);
set_worst_input_latency ();
update_route_latency (false, false);