13
0

Fix crash when session-load fails while creating Routes

When loading the state of a Route fails (here
"unknown enumerator SurroundMaster in PBD::EnumWriter"), the
routes which have already been loaded are not added to the
Session's routelist.

Already existing routes that have an InternalSend or have
a circular reference:

The Send's `_send_from` holds a shared pointer
`<Route>(shared_from_this())` to the Route, and the
Route's ProcessorList contains the InternalSend.

This leads to various
"SessionHandleRef exists across session deletion" of
IO, Ports, GraphNode, Graph, etc
which causes issues when loading another session.

Session::destroy() cleans calls drop_references for
each route in the RouteList, which breaks the circular
dependency (InternalSend drops reference to Route).
But here the RouteList is empty.

Crash fixed:
 * Load a session that fails to load a Route
  (here a session created on with the vapor branch, on master)
 * Then load another session without restarting Ardour.
This commit is contained in:
Robin Gareus 2024-01-06 04:18:36 +01:00
parent e8a902d875
commit 58641d2a35
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04

View File

@ -2118,17 +2118,21 @@ Session::load_routes (const XMLNode& node, int version)
std::shared_ptr<Route> route;
if (version < 3000) {
route = XMLRouteFactory_2X (**niter, version);
} else if (version < 5000) {
route = XMLRouteFactory_3X (**niter, version);
} else {
route = XMLRouteFactory (**niter, version);
try {
if (version < 3000) {
route = XMLRouteFactory_2X (**niter, version);
} else if (version < 5000) {
route = XMLRouteFactory_3X (**niter, version);
} else {
route = XMLRouteFactory (**niter, version);
}
} catch (...) {
goto errout;
}
if (route == 0) {
error << _("Session: cannot create track/bus from XML description.") << endmsg;
return -1;
goto errout;
}
BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
@ -2153,6 +2157,12 @@ Session::load_routes (const XMLNode& node, int version)
BootMessage (_("Finished adding tracks/busses"));
return 0;
errout:
for (auto const& r : new_routes) {
r->drop_references ();
}
return -1;
}
std::shared_ptr<Route>