From: <man...@us...> - 2015-04-23 10:42:03
|
Revision: 4970 http://sourceforge.net/p/modplug/code/4970 Author: manxorist Date: 2015-04-23 10:41:49 +0000 (Thu, 23 Apr 2015) Log Message: ----------- [Mod] Crash handler: Add [Debug]StopSoundDeviceBeforeDump (default false) setting and change the default behaviour to stop the audio device after dumping the crash information. This helps debugging crashes inside the audio thread/callback with the default settings. [Mod] sounddev: Add DebugIsFragileDevice() and DebugInRealtimeCallback() to SoundDevice::IBase which allows audio devices to override the behaviour in case of a crash. ASIO devices sort of require this as they tend to provoke kernel crashes when not stopped and closed properly. DebugIsFragileDevice() return true for all ASIO devices and false otherwise. DebugInRealtimeCallback() is only required to be implemented when the device is flagged as fragile, otherwise it just returns false. [Mod] Crash handler: Override the configured behaviour regarding stopping the audio device for fragile (ASIO) sound devices: In case the crash happens inside the audio callback, the device is always closed after writing out the dump. In the case the crash happens outside of the callback, the device is always closed before writing the dump. Modified Paths: -------------- trunk/OpenMPT/mptrack/ExceptionHandler.cpp trunk/OpenMPT/mptrack/ExceptionHandler.h trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/mptrack/TrackerSettings.h trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp trunk/OpenMPT/sounddev/SoundDeviceASIO.h Modified: trunk/OpenMPT/mptrack/ExceptionHandler.cpp =================================================================== --- trunk/OpenMPT/mptrack/ExceptionHandler.cpp 2015-04-23 10:04:53 UTC (rev 4969) +++ trunk/OpenMPT/mptrack/ExceptionHandler.cpp 2015-04-23 10:41:49 UTC (rev 4970) @@ -27,6 +27,7 @@ bool ExceptionHandler::fullMemDump = false; bool ExceptionHandler::stopSoundDeviceOnCrash = true; +bool ExceptionHandler::stopSoundDeviceBeforeDump = false; enum DumpMode @@ -91,12 +92,15 @@ int rescuedFiles; private: static bool FreezeState(DumpMode mode); + static bool Cleanup(DumpMode mode); bool GenerateDump(_EXCEPTION_POINTERS *pExceptionInfo); bool GenerateTraceLog(); int RescueFiles(); bool HasWrittenDebug() const { return writtenMiniDump || writtenTraceLog; } + static void StopSoundDevice(); public: DebugReporter(DumpMode mode, _EXCEPTION_POINTERS *pExceptionInfo); + ~DebugReporter(); void ReportError(CString errorMessage); }; @@ -124,6 +128,13 @@ } +DebugReporter::~DebugReporter() +//----------------------------- +{ + Cleanup(mode); +} + + bool DebugReporter::GenerateDump(_EXCEPTION_POINTERS *pExceptionInfo) //------------------------------------------------------------------- { @@ -225,27 +236,19 @@ if(mode == DumpModeCrash || mode == DumpModeWarning) { - // Shut down audio device... - if(ExceptionHandler::stopSoundDeviceOnCrash) + if(CMainFrame::GetMainFrame() && CMainFrame::GetMainFrame()->gpSoundDevice && CMainFrame::GetMainFrame()->gpSoundDevice->DebugIsFragileDevice()) { - CMainFrame* pMainFrame = CMainFrame::GetMainFrame(); - if(pMainFrame) + // For fragile devices, always stop the device. Stop before the dumping if not in realtime context. + if(!CMainFrame::GetMainFrame()->gpSoundDevice->DebugInRealtimeCallback()) { - try - { - if(pMainFrame->gpSoundDevice) - { - pMainFrame->gpSoundDevice->Close(); - } - if(pMainFrame->m_NotifyTimer) - { - pMainFrame->KillTimer(pMainFrame->m_NotifyTimer); - pMainFrame->m_NotifyTimer = 0; - } - } catch(...) - { - } + StopSoundDevice(); } + } else + { + if(ExceptionHandler::stopSoundDeviceOnCrash && ExceptionHandler::stopSoundDeviceBeforeDump) + { + StopSoundDevice(); + } } } @@ -253,7 +256,57 @@ } +void DebugReporter::StopSoundDevice() +//----------------------------------- +{ + CMainFrame* pMainFrame = CMainFrame::GetMainFrame(); + if(pMainFrame) + { + try + { + if(pMainFrame->gpSoundDevice) + { + pMainFrame->gpSoundDevice->Close(); + } + if(pMainFrame->m_NotifyTimer) + { + pMainFrame->KillTimer(pMainFrame->m_NotifyTimer); + pMainFrame->m_NotifyTimer = 0; + } + } catch(...) + { + } + } +} + +bool DebugReporter::Cleanup(DumpMode mode) +//---------------------------------------- +{ + MPT_TRACE(); + + if(mode == DumpModeCrash || mode == DumpModeWarning) + { + if(CMainFrame::GetMainFrame() && CMainFrame::GetMainFrame()->gpSoundDevice && CMainFrame::GetMainFrame()->gpSoundDevice->DebugIsFragileDevice()) + { + // For fragile devices, always stop the device. Stop after the dumping if in realtime context. + if(CMainFrame::GetMainFrame()->gpSoundDevice->DebugInRealtimeCallback()) + { + StopSoundDevice(); + } + } else + { + if(ExceptionHandler::stopSoundDeviceOnCrash && !ExceptionHandler::stopSoundDeviceBeforeDump) + { + StopSoundDevice(); + } + } + } + + return true; +} + + // Different entry points for different situations in which we want to dump some information Modified: trunk/OpenMPT/mptrack/ExceptionHandler.h =================================================================== --- trunk/OpenMPT/mptrack/ExceptionHandler.h 2015-04-23 10:04:53 UTC (rev 4969) +++ trunk/OpenMPT/mptrack/ExceptionHandler.h 2015-04-23 10:41:49 UTC (rev 4970) @@ -19,6 +19,7 @@ public: static bool fullMemDump; static bool stopSoundDeviceOnCrash; + static bool stopSoundDeviceBeforeDump; // Call this to activate unhandled exception filtering. static void Register() { ::SetUnhandledExceptionFilter(UnhandledExceptionFilter); }; Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2015-04-23 10:04:53 UTC (rev 4969) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2015-04-23 10:41:49 UTC (rev 4970) @@ -239,11 +239,13 @@ , DebugTraceSize(conf, "Debug", "TraceSize", 1000000) , DebugTraceAlwaysDump(conf, "Debug", "TraceAlwaysDump", false) , DebugStopSoundDeviceOnCrash(conf, "Debug", "StopSoundDeviceOnCrash", true) + , DebugStopSoundDeviceBeforeDump(conf, "Debug", "StopSoundDeviceBeforeDump", false) { // Debug - // Duplicate state for debug stffu in order to avoid calling into settings fremwork from crash conetxt. + // Duplicate state for debug stuff in order to avoid calling into settings framework from crash context. ExceptionHandler::stopSoundDeviceOnCrash = DebugStopSoundDeviceOnCrash; + ExceptionHandler::stopSoundDeviceBeforeDump = DebugStopSoundDeviceBeforeDump; // Effects #ifndef NO_DSP Modified: trunk/OpenMPT/mptrack/TrackerSettings.h =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.h 2015-04-23 10:04:53 UTC (rev 4969) +++ trunk/OpenMPT/mptrack/TrackerSettings.h 2015-04-23 10:41:49 UTC (rev 4970) @@ -568,6 +568,7 @@ Setting<bool> DebugTraceAlwaysDump; Setting<bool> DebugStopSoundDeviceOnCrash; + Setting<bool> DebugStopSoundDeviceBeforeDump; public: Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2015-04-23 10:04:53 UTC (rev 4969) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2015-04-23 10:41:49 UTC (rev 4970) @@ -533,6 +533,10 @@ virtual SoundDevice::TimeInfo GetTimeInfo() const = 0; virtual int64 GetStreamPositionFrames() const = 0; + // Debugging aids in case of a crash + virtual bool DebugIsFragileDevice() const = 0; + virtual bool DebugInRealtimeCallback() const = 0; + // Informational only, do not use for timing. // Use GetStreamPositionFrames() for timing virtual SoundDevice::Statistics GetStatistics() const = 0; @@ -667,6 +671,9 @@ SoundDevice::TimeInfo GetTimeInfo() const { return m_TimeInfo; } int64 GetStreamPositionFrames() const; + virtual bool DebugIsFragileDevice() const { return false; } + virtual bool DebugInRealtimeCallback() const { return false; } + virtual SoundDevice::Statistics GetStatistics() const; virtual bool OpenDriverSettings() { return false; }; Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2015-04-23 10:04:53 UTC (rev 4969) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2015-04-23 10:41:49 UTC (rev 4970) @@ -214,6 +214,9 @@ InterlockedExchange(&m_RenderingSilence, 0); InterlockedExchange(&m_AsioRequestFlags, 0); + + m_DebugRealtimeThreadID.store(0); + } @@ -1104,6 +1107,20 @@ //----------------------------------------------------------------------------------------------------------- { MPT_TRACE(); + struct DebugRealtimeThreadIdGuard + { + mpt::atomic_uint32_t & ThreadID; + DebugRealtimeThreadIdGuard(mpt::atomic_uint32_t & ThreadID) + : ThreadID(ThreadID) + { + ThreadID.store(GetCurrentThreadId()); + } + ~DebugRealtimeThreadIdGuard() + { + ThreadID.store(0); + } + }; + DebugRealtimeThreadIdGuard debugThreadIdGuard(m_DebugRealtimeThreadID); MPT_ASSERT(directProcess); // !directProcess is not handled correctly in OpenMPT, would require a separate thread and potentially additional buffering if(!directProcess) { @@ -1204,6 +1221,20 @@ } +bool CASIODevice::DebugIsFragileDevice() const +//-------------------------------------------- +{ + return true; +} + + +bool CASIODevice::DebugInRealtimeCallback() const +//----------------------------------------------- +{ + return GetCurrentThreadId() == m_DebugRealtimeThreadID.load(); +} + + SoundDevice::Statistics CASIODevice::GetStatistics() const //-------------------------------------------------------- { Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2015-04-23 10:04:53 UTC (rev 4969) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2015-04-23 10:41:49 UTC (rev 4970) @@ -80,6 +80,8 @@ FlagSet<AsioFeatures> m_QueriedFeatures; FlagSet<AsioFeatures> m_UsedFeatures; + mutable mpt::atomic_uint32_t m_DebugRealtimeThreadID; + private: void UpdateTimeInfo(AsioTimeInfo asioTimeInfo); @@ -118,6 +120,9 @@ bool OpenDriverSettings(); + bool DebugIsFragileDevice() const; + bool DebugInRealtimeCallback() const; + SoundDevice::Statistics GetStatistics() const; public: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |