From 58641d2a3595cb8f7c90a25c3c88aa2353f3c8e3 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sat, 6 Jan 2024 04:18:36 +0100 Subject: [PATCH] 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 `(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. --- libs/ardour/session_state.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 51d4ed6a91..ee2189d725 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -2118,17 +2118,21 @@ Session::load_routes (const XMLNode& node, int version) std::shared_ptr 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