Fix export race condition (and crash)
Previously the freewheel export thread directly called Session::butler_transport_work(). The butler thread may concurrently call the same function. This can lead double free or memory corruption (see below) Now export thread summons the butler and does nothing until it completed its work. ``` Export Thread: 3 XMLNode::~XMLNode 4 ARDOUR::AutomationList::snapshot_history 5 ARDOUR::AutomationList::start_write_pass 6 ARDOUR::Automatable::non_realtime_locate 7 ARDOUR::Route::non_realtime_locate 8 ARDOUR::Session::non_realtime_locate 9 ARDOUR::Session::butler_transport_work 10 ARDOUR::Session::process_export_fw Butler thread: 7 XMLNode::~XMLNode 8 ARDOUR::AutomationList::snapshot_history 9 ARDOUR::AutomationList::start_write_pass 10 ARDOUR::Automatable::non_realtime_locate 11 ARDOUR::Route::non_realtime_locate 12 ARDOUR::Session::non_realtime_locate 13 ARDOUR::Session::butler_transport_work 14 ARDOUR::Butler::thread_work 15 ARDOUR::Butler::_thread_work ```
This commit is contained in:
parent
cc83cdd9df
commit
79bf025862
@ -307,9 +307,8 @@ Session::process_export_fw (pframes_t nframes)
|
||||
|
||||
TFSM_SPEED (1.0, false);
|
||||
TFSM_ROLL ();
|
||||
butler_transport_work (true);
|
||||
g_atomic_int_set (&_butler->should_do_transport_work, 0);
|
||||
butler_completed_transport_work ();
|
||||
_butler->schedule_transport_work ();
|
||||
|
||||
/* Session::process_with_events () sets _remaining_latency_preroll = 0
|
||||
* when being called with _transport_fsm->transport_speed() == 0.
|
||||
*
|
||||
@ -323,6 +322,16 @@ Session::process_export_fw (pframes_t nframes)
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait for butler to complete schedule_transport_work(),
|
||||
* compare to Session::process */
|
||||
if (non_realtime_work_pending ()) {
|
||||
if (_butler->transport_work_requested ()) {
|
||||
/* butler is still processing */
|
||||
return;
|
||||
}
|
||||
butler_completed_transport_work ();
|
||||
}
|
||||
|
||||
if (_remaining_latency_preroll > 0) {
|
||||
samplepos_t remain = std::min ((samplepos_t)nframes, _remaining_latency_preroll);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user