Fix deadlock during export

When using the export-tool, the very first callback may already be
freewheeling. In this case the first call to the butler also happens
directly from the freewheel process-callback and initial session events
are handled there. Setting PostTransportAdjustPlaybackBuffering
took the process-lock, which caused a deadlock:


Glib::Threads::Mutex::Lock::Lock(Glib::Threads::Mutex&) at /usr/include/glibmm-2.4/glibmm/threads.h:687
ARDOUR::Session::butler_transport_work() at ../libs/ardour/session_transport.cc:1157
ARDOUR::Session::process_export_fw(unsigned int) at ../libs/ardour/session_export.cc:303
ARDOUR::AudioEngine::process_callback(unsigned int) at ../libs/ardour/audioengine.cc:486
ARDOUR::DummyAudioBackend::main_process_thread() at ../libs/backends/dummy/dummy_audiobackend.cc:951
This commit is contained in:
Robin Gareus 2020-12-08 01:08:49 +01:00
parent 2a011e19cb
commit f8b5424d9f
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
3 changed files with 11 additions and 5 deletions

View File

@ -304,7 +304,7 @@ public:
void refill_all_track_buffers ();
Butler* butler() { return _butler; }
void butler_transport_work ();
void butler_transport_work (bool have_process_lock = false);
void refresh_disk_space ();

View File

@ -300,7 +300,7 @@ Session::process_export_fw (pframes_t nframes)
}
set_transport_speed (1.0, false, false, false);
butler_transport_work ();
butler_transport_work (true);
g_atomic_int_set (&_butler->should_do_transport_work, 0);
butler_completed_transport_work ();
/* Session::process_with_events () sets _remaining_latency_preroll = 0

View File

@ -1099,7 +1099,7 @@ Session::solo_selection (StripableList &list, bool new_state)
void
Session::butler_transport_work ()
Session::butler_transport_work (bool have_process_lock)
{
/* Note: this function executes in the butler thread context */
@ -1154,7 +1154,10 @@ Session::butler_transport_work ()
if (ptw & PostTransportAdjustPlaybackBuffering) {
/* need to prevent concurrency with ARDOUR::Reader::run(),
* DiskWriter::adjust_buffering() re-allocates the ringbuffer */
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
if (!have_process_lock) {
lx.acquire ();
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
if (tr) {
@ -1172,7 +1175,10 @@ Session::butler_transport_work ()
if (ptw & PostTransportAdjustCaptureBuffering) {
/* need to prevent concurrency with ARDOUR::DiskWriter::run(),
* DiskWriter::adjust_buffering() re-allocates the ringbuffer */
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
if (!have_process_lock) {
lx.acquire ();
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
if (tr) {