Fix potential deadlock
block_processing() may hold the process-lock, waiting for the latency-lock. at the same time audio-engine may hold the latter, trying to acquire the former.
This commit is contained in:
parent
fec679c602
commit
6900facef2
@ -1469,7 +1469,7 @@ private:
|
||||
|
||||
samplecnt_t calc_preroll_subcycle (samplecnt_t) const;
|
||||
|
||||
void block_processing() { g_atomic_int_set (&_processing_prohibited, 1); }
|
||||
void block_processing();
|
||||
void unblock_processing() { g_atomic_int_set (&_processing_prohibited, 0); }
|
||||
bool processing_blocked() const { return g_atomic_int_get (&_processing_prohibited); }
|
||||
|
||||
|
@ -308,25 +308,32 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||
lc = true;
|
||||
}
|
||||
if (lp || lc) {
|
||||
Glib::Threads::Mutex::Lock ll (_latency_lock);
|
||||
tm.release ();
|
||||
/* re-check after releasing lock */
|
||||
if (_session->processing_blocked ()) {
|
||||
/* synchronize with Session::processing_blocked
|
||||
* This lock is not contended by this thread, but acts
|
||||
* as barrier for Session::block_processing (Session::write_one_track).
|
||||
*/
|
||||
Glib::Threads::Mutex::Lock ll (_latency_lock, Glib::Threads::TRY_LOCK);
|
||||
/* re-check after talking latency-lock */
|
||||
if (!ll.locked () || _session->processing_blocked ()) {
|
||||
if (lc) {
|
||||
g_atomic_int_set (&_pending_capture_latency_callback, 1);
|
||||
queue_latency_update (false);
|
||||
}
|
||||
if (lp) {
|
||||
g_atomic_int_set (&_pending_playback_latency_callback, 1);
|
||||
queue_latency_update (true);
|
||||
}
|
||||
} else {
|
||||
/* release process-lock to call Session::update_latency */
|
||||
tm.release ();
|
||||
if (lc) {
|
||||
_session->update_latency (false);
|
||||
}
|
||||
if (lp) {
|
||||
_session->update_latency (true);
|
||||
}
|
||||
/* release latency lock, **before** reacquiring process-lock */
|
||||
ll.release ();
|
||||
tm.acquire ();
|
||||
}
|
||||
tm.acquire ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1485,8 +1492,8 @@ AudioEngine::latency_callback (bool for_playback)
|
||||
* async to connect/disconnect or port creation/deletion.
|
||||
* All is fine.
|
||||
*/
|
||||
Glib::Threads::Mutex::Lock ll (_latency_lock);
|
||||
if (_session->processing_blocked ()) {
|
||||
Glib::Threads::Mutex::Lock ll (_latency_lock, Glib::Threads::TRY_LOCK);
|
||||
if (!ll.locked () || _session->processing_blocked ()) {
|
||||
/* Except Session::write_one_track() might just have called block_processing() */
|
||||
queue_latency_update (for_playback);
|
||||
} else {
|
||||
|
@ -846,6 +846,21 @@ Session::destroy ()
|
||||
BOOST_SHOW_POINTERS ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Session::block_processing()
|
||||
{
|
||||
g_atomic_int_set (&_processing_prohibited, 1);
|
||||
|
||||
/* processing_blocked() is only checked at the beginning
|
||||
* of the next cycle. So wait until any ongoing
|
||||
* process-callback returns.
|
||||
*/
|
||||
Glib::Threads::Mutex::Lock lm (_engine.process_lock());
|
||||
/* latency callback may be in process, wait until it completed */
|
||||
Glib::Threads::Mutex::Lock lx (_engine.latency_lock());
|
||||
}
|
||||
|
||||
void
|
||||
Session::setup_ltc ()
|
||||
{
|
||||
@ -5752,20 +5767,11 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end,
|
||||
return result;
|
||||
}
|
||||
|
||||
// block all process callback handling
|
||||
|
||||
/* block all process callback handling, so that thread-buffers
|
||||
* are available here.
|
||||
*/
|
||||
block_processing ();
|
||||
|
||||
{
|
||||
// synchronize with AudioEngine::process_callback()
|
||||
// make sure processing is not currently running
|
||||
// and processing_blocked() is honored before
|
||||
// acquiring thread buffers
|
||||
Glib::Threads::Mutex::Lock lm (_engine.process_lock());
|
||||
/* latency callback may be in process, wait until complete */
|
||||
Glib::Threads::Mutex::Lock lx (_engine.latency_lock());
|
||||
}
|
||||
|
||||
_bounce_processing_active = true;
|
||||
|
||||
/* call tree *MUST* hold route_lock */
|
||||
|
Loading…
Reference in New Issue
Block a user