diff --git a/ApplicationExeCode/RiaGrpcConsoleApplication.cpp b/ApplicationExeCode/RiaGrpcConsoleApplication.cpp index dae4ef68d2..f61954f6cb 100644 --- a/ApplicationExeCode/RiaGrpcConsoleApplication.cpp +++ b/ApplicationExeCode/RiaGrpcConsoleApplication.cpp @@ -17,6 +17,8 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaGrpcConsoleApplication.h" +#include "RiaMainTools.h" + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -30,6 +32,11 @@ QProcessEnvironment RiaGrpcConsoleApplication::pythonProcessEnvironment() const //-------------------------------------------------------------------------------------------------- void RiaGrpcConsoleApplication::doIdleProcessing() { + // The crash handler pumps the event loop while flushing telemetry, so this timer slot can fire + // mid-crash. Processing requests or closing the project would then destroy objects the crashed + // code still uses, causing a nested crash. + if ( RiaMainTools::isCrashHandlingInProgress() ) return; + int processCount = processRequests(); if ( processCount == -1 ) { diff --git a/ApplicationExeCode/RiaGrpcGuiApplication.cpp b/ApplicationExeCode/RiaGrpcGuiApplication.cpp index f6a36c3e64..fc9ae26c84 100644 --- a/ApplicationExeCode/RiaGrpcGuiApplication.cpp +++ b/ApplicationExeCode/RiaGrpcGuiApplication.cpp @@ -17,6 +17,7 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaGrpcGuiApplication.h" +#include "RiaMainTools.h" #include "RiaPreferences.h" #include "cafProgressInfo.h" @@ -55,6 +56,11 @@ QProcessEnvironment RiaGrpcGuiApplication::pythonProcessEnvironment() const //-------------------------------------------------------------------------------------------------- void RiaGrpcGuiApplication::doIdleProcessing() { + // The crash handler pumps the event loop while flushing telemetry, so this timer slot can fire + // mid-crash. Processing requests or closing the project would then destroy objects the crashed + // code still uses, causing a nested crash. + if ( RiaMainTools::isCrashHandlingInProgress() ) return; + if ( !caf::ProgressInfoStatic::isRunning() ) { int processCount = processRequests(); diff --git a/ApplicationExeCode/RiaMainTools.cpp b/ApplicationExeCode/RiaMainTools.cpp index 55a11ff45c..ac31546e21 100644 --- a/ApplicationExeCode/RiaMainTools.cpp +++ b/ApplicationExeCode/RiaMainTools.cpp @@ -32,6 +32,7 @@ #include +#include #include #include #include @@ -156,6 +157,8 @@ static std::string signalCodeDescription( int signo, int siCode ) #endif } // namespace internal +static std::atomic s_crashHandlingInProgress( false ); + //-------------------------------------------------------------------------------------------------- /// Shared crash logging: writes to file logger and OpenTelemetry. /// extraAttrs may include platform-specific context like fault address and signal code description. @@ -166,6 +169,11 @@ static std::string signalCodeDescription( int signo, int siCode ) //-------------------------------------------------------------------------------------------------- static void performCrashLogging( int signalCode, const std::map& extraAttrs ) { + // Block timer-driven application logic (e.g. gRPC idle processing) for the rest of the process + // lifetime: the telemetry flush below pumps the event loop, and a timer slot firing there could + // close the project and destroy objects the crashed code still uses, causing a nested crash. + s_crashHandlingInProgress = true; + #if RIA_HAS_STD_STACKTRACE auto st = std::stacktrace::current(); #endif @@ -306,6 +314,14 @@ void manageSegFailureSA( int signalCode, siginfo_t* info, void* ucontext ) namespace RiaMainTools { +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool isCrashHandlingInProgress() +{ + return s_crashHandlingInProgress; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationExeCode/RiaMainTools.h b/ApplicationExeCode/RiaMainTools.h index d3add41c2e..164e203d04 100644 --- a/ApplicationExeCode/RiaMainTools.h +++ b/ApplicationExeCode/RiaMainTools.h @@ -22,4 +22,9 @@ namespace RiaMainTools void initializeSingletons(); void releaseSingletonAndFactoryObjects(); void deleteStaleSettingsLockFiles(); + +// True once crash logging has started. The crash handler pumps the Qt event loop while flushing +// telemetry, so timer-driven application logic must check this flag and stay idle to avoid +// re-entering or tearing down objects the crashed code still uses. +bool isCrashHandlingInProgress(); }; // namespace RiaMainTools