Drop TMM ports when closing session, or backend goes away

TMM ports cannot exist without a backend.
This fixes crashes where the PortEngine is re-initialized
(backend change):

Previously, TMM ports were only dropped (and recreated)
in TMM::restart() called from ARDOUR::init_post_engine().
When starting a new backend the old one is already destroyed,
but TM still held reference to Ports owned by that backend.
Calling the port's d'tor caused a memory corruption trying to
acquire the backend's port_callback_mutex:

e.g. When creating new session with a different backend
from a running instance, or unit-test after call to
AudioEngine::destroy(): https://pastebin.com/4D6pLA5s
This commit is contained in:
Robin Gareus 2020-10-22 07:37:07 +02:00
parent 8bc3e86066
commit 32a0c6a3ff
No known key found for this signature in database
GPG key ID: A090BCE02CF57F04
2 changed files with 8 additions and 1 deletions

View file

@ -942,6 +942,7 @@ AudioEngine::drop_backend ()
Port::PortDrop (); /* EMIT SIGNAL */
TransportMasterManager& tmm (TransportMasterManager::instance());
tmm.engine_stopped ();
tmm.set_session (0); // unregister TMM ports
/* Stopped is needed for Graph to explicitly terminate threads */
Stopped (); /* EMIT SIGNAL */

View file

@ -74,7 +74,7 @@ TransportMaster::TransportMaster (SyncSource t, std::string const & name)
, _sclock_synced (Properties::sclock_synced, false)
, _collect (Properties::collect, true)
, _connected (Properties::connected, false)
, port_node (X_(""))
, port_node (X_("Port"))
{
register_properties ();
@ -243,6 +243,9 @@ void
TransportMaster::set_session (Session* s)
{
_session = s;
if (!_session) {
unregister_port ();
}
}
int
@ -325,7 +328,10 @@ TransportMaster::get_state ()
}
}
port_node = *pnode;
node->add_child_nocopy (*pnode);
} else if (port_node.children (). size() > 0) {
node->add_child_copy (port_node);
}
return *node;