From 0f0006cebcc95daca46fd4359ce540deb5f0ffc3 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 6 Nov 2024 03:41:17 +0100 Subject: [PATCH] Debug set_session(0) calls preventing session_going_away() --- libs/ardour/ardour/session_handle.h | 22 +++++++++++---- libs/ardour/audioengine.cc | 5 ++++ libs/ardour/session_handle.cc | 44 +++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/libs/ardour/ardour/session_handle.h b/libs/ardour/ardour/session_handle.h index cf2e04dda5..0c660ca054 100644 --- a/libs/ardour/ardour/session_handle.h +++ b/libs/ardour/ardour/session_handle.h @@ -22,24 +22,29 @@ #include "ardour/libardour_visibility.h" +#ifndef NDEBUG +# define TRACE_SETSESSION_NULL +#endif + namespace ARDOUR { class Session; class LIBARDOUR_API SessionHandleRef : public PBD::ScopedConnectionList { - public: +public: SessionHandleRef (ARDOUR::Session& s); virtual ~SessionHandleRef (); - protected: - ARDOUR::Session& _session; +protected: virtual void session_going_away (); virtual void insanity_check (); + + ARDOUR::Session& _session; }; class LIBARDOUR_API SessionHandlePtr { - public: +public: SessionHandlePtr (ARDOUR::Session* s); SessionHandlePtr () : _session (0) {} virtual ~SessionHandlePtr () {} @@ -47,11 +52,16 @@ class LIBARDOUR_API SessionHandlePtr virtual void set_session (ARDOUR::Session *); virtual ARDOUR::Session* session() const { return _session; } - protected: +protected: + virtual void session_going_away (); + ARDOUR::Session* _session; PBD::ScopedConnectionList _session_connections; - virtual void session_going_away (); +#ifdef TRACE_SETSESSION_NULL +private: + bool _gone_away_emitted; +#endif }; } /* namespace */ diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 99bb95f12b..481c6dab16 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -463,7 +463,12 @@ AudioEngine::process_callback (pframes_t nframes) /* fade out done */ PortManager::silence_outputs (nframes); session_deleted = true; +#ifdef TRACE_SETSESSION_NULL + _session_connections.drop_connections (); + _session = 0; +#else SessionHandlePtr::set_session (0); +#endif session_removal_countdown = -1; // reset to "not in progress" session_remove_pending = false; session_removed.signal(); // wakes up thread that initiated session removal diff --git a/libs/ardour/session_handle.cc b/libs/ardour/session_handle.cc index a8dc792f3f..8a0f246a26 100644 --- a/libs/ardour/session_handle.cc +++ b/libs/ardour/session_handle.cc @@ -19,6 +19,11 @@ #include "pbd/demangle.h" #include "pbd/error.h" +#ifdef TRACE_SETSESSION_NULL +#include +#include "pbd/stacktrace.h" +#endif + #include "ardour/boost_debug.h" #include "ardour/session.h" #include "ardour/session_handle.h" @@ -31,6 +36,9 @@ using namespace PBD; SessionHandlePtr::SessionHandlePtr (Session* s) : _session (s) +#ifdef TRACE_SETSESSION_NULL + , _gone_away_emitted (false) +#endif { if (_session) { _session->DropReferences.connect_same_thread (_session_connections, std::bind (&SessionHandlePtr::session_going_away, this)); @@ -42,6 +50,32 @@ SessionHandlePtr::set_session (Session* s) { _session_connections.drop_connections (); +#ifdef TRACE_SETSESSION_NULL + /* DropReferences may already have been disconnected due to signal emission ordering. + * + * An instance of this class (e.g. Ardour_UI) will need to call ::set_session() on member instances. + * + * Yet, when session_going_away() first calls set_session (0) on an instance that has SessionHandlePtr members, + * they will reach here, and disocnnect signal handlers. Their derived implementation of ::session_going_away() + * will not be called. + */ + if (!_gone_away_emitted && _session && !s) { + /* if this assert goes off, some ::set_session() implementation calls + * some_member->set_session (0); + * + * replace it with + * + * if (session) { + * some_member->set_session (session); + * } + */ + PBD::stacktrace (cerr, 10); + assert (0); + _gone_away_emitted = true; + session_going_away (); + } +#endif + if (_session) { _session = 0; } @@ -49,13 +83,23 @@ SessionHandlePtr::set_session (Session* s) if (s) { _session = s; _session->DropReferences.connect_same_thread (_session_connections, std::bind (&SessionHandlePtr::session_going_away, this)); +#ifdef TRACE_SETSESSION_NULL + _gone_away_emitted = false; +#endif } } void SessionHandlePtr::session_going_away () { +#ifdef TRACE_SETSESSION_NULL + if (_session && !_gone_away_emitted) { + _gone_away_emitted = true; + set_session (0); + } +#else set_session (0); +#endif } /*-------------------------*/