From 8f0fd4f10a4d4e62c213d5ea8b7d4d4f00093a5f Mon Sep 17 00:00:00 2001 From: SatheeshkumarG15 Date: Wed, 8 Jul 2026 20:39:07 +0530 Subject: [PATCH 1/8] postmortem: add configurable sink controls for WorkerPool and callstack dumps Introduces PostMortemDataSink enum (FILE/LOG/ALL/DISABLED) to independently control where WorkerPool JSON snapshots and callstack dumps are written on crash. Defaults: wpSink=FILE, csSink=DISABLED. - Config.h: add PostMortemDataSink enum, parse helpers, new accessors - CMakeLists.txt: add POSTMORTEM_WORKERPOOL_SINK / POSTMORTEM_CALLSTACK_SINK CMake options with compile-time defaults - GenericConfig.cmake / WPEFramework.conf.in / params.config: expose new config keys (postmortemworkerpoolsink, postmortemcallstacksink, postmortemcallstackdumppath) - PluginServer.h: gate DumpCallStack, file write, and syslog output behind runtime sink checks; add DumpReadableMetadata() for human-readable ThunderInternals.txt output --- Source/Thunder/CMakeLists.txt | 23 +++++++++++++ Source/Thunder/Config.h | 54 ++++++++++++++++++++++++++++++ Source/Thunder/GenericConfig.cmake | 4 +++ Source/Thunder/PluginServer.h | 45 ++++++++++++++++++++----- Source/Thunder/Thunder.conf.in | 3 ++ Source/Thunder/params.config | 3 ++ 6 files changed, 123 insertions(+), 9 deletions(-) diff --git a/Source/Thunder/CMakeLists.txt b/Source/Thunder/CMakeLists.txt index b2632e942..5589abb1d 100644 --- a/Source/Thunder/CMakeLists.txt +++ b/Source/Thunder/CMakeLists.txt @@ -22,6 +22,27 @@ get_filename_component(TARGET ${CMAKE_CURRENT_SOURCE_DIR} NAME) set(THREADPOOL_COUNT "4" CACHE STRING "The number of threads in the thread pool") set(ENABLE_TRACING_MODULES "" CACHE STRING "A space separated list of specific tracing modules to be enabled at start.") +macro(thunder_postmortem_sink_value VAR_IN VAR_OUT) + string(TOUPPER "${${VAR_IN}}" _s) + if (_s STREQUAL "LOG") + set(${VAR_OUT} 1) + elseif(_s STREQUAL "ALL") + set(${VAR_OUT} 2) + elseif(_s STREQUAL "DISABLED") + set(${VAR_OUT} 3) + else() + set(${VAR_OUT} 0) + endif() +endmacro() + +set(POSTMORTEM_WORKERPOOL_SINK "FILE" CACHE STRING "Default WorkerPool JSON dump sink on crash (FILE | LOG | ALL | DISABLED)") +set(POSTMORTEM_CALLSTACK_SINK "DISABLED" CACHE STRING "Default inline callstack print sink on crash (FILE | LOG | ALL | DISABLED)") +set_property(CACHE POSTMORTEM_WORKERPOOL_SINK PROPERTY STRINGS FILE LOG ALL DISABLED) +set_property(CACHE POSTMORTEM_CALLSTACK_SINK PROPERTY STRINGS FILE LOG ALL DISABLED) + +thunder_postmortem_sink_value(POSTMORTEM_WORKERPOOL_SINK _wp_sink) +thunder_postmortem_sink_value(POSTMORTEM_CALLSTACK_SINK _cs_sink) + option(SKIP_PERSISTENT_PATH_INSTALL "This will skip installing the persistent path and its privileges. Needed for local build/installs" OFF) add_executable(${TARGET} @@ -38,6 +59,8 @@ target_compile_definitions(${TARGET} NAMESPACE=${NAMESPACE} APPLICATION_NAME=${TARGET} THREADPOOL_COUNT=${THREADPOOL_COUNT} + THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=${_wp_sink} + THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=${_cs_sink} ) target_compile_options (${TARGET} PRIVATE -Wno-psabi) diff --git a/Source/Thunder/Config.h b/Source/Thunder/Config.h index cc2dc43ee..730aa6bc3 100644 --- a/Source/Thunder/Config.h +++ b/Source/Thunder/Config.h @@ -25,6 +25,25 @@ namespace Thunder { namespace PluginHost { + + enum class PostMortemDataSink : uint8_t { + FILE = 0, + LOG = 1, + ALL = 2, + DISABLED = 3 + }; + + static inline PostMortemDataSink ParsePostMortemDataSink(const string& input, PostMortemDataSink fallback) + { + string s(input); + std::transform(s.begin(), s.end(), s.begin(), ::tolower); + if (s == _T("log")) return PostMortemDataSink::LOG; + else if (s == _T("all")) return PostMortemDataSink::ALL; + else if (s == _T("disabled")) return PostMortemDataSink::DISABLED; + else if (s == _T("file")) return PostMortemDataSink::FILE; + return fallback; + } + /** * IMPORTANT: If updating this class to add/remove/modify configuration options, ensure * the documentation in docs/introduction/config.md is updated to reflect the changes! @@ -459,6 +478,9 @@ namespace PluginHost { Add(_T("volatilepath"), &VolatilePath); Add(_T("proxystubpath"), &ProxyStubPath); Add(_T("postmortempath"), &PostMortemPath); + Add(_T("postmortemworkerpoolsink"), &PostMortemWorkerPoolSink); + Add(_T("postmortemcallstacksink"), &PostMortemCallstackSink); + Add(_T("postmortemcallstackdumppath"), &PostMortemCallstackDumpPath); Add(_T("communicator"), &Communicator); Add(_T("signature"), &Signature); Add(_T("idletime"), &IdleTime); @@ -515,6 +537,9 @@ namespace PluginHost { Core::JSON::String VolatilePath; Core::JSON::String ProxyStubPath; Core::JSON::String PostMortemPath; + Core::JSON::String PostMortemWorkerPoolSink; + Core::JSON::String PostMortemCallstackSink; + Core::JSON::String PostMortemCallstackDumpPath; Core::JSON::String Communicator; Core::JSON::String Redirect; Core::JSON::String Signature; @@ -695,6 +720,9 @@ namespace PluginHost { , _proxyStubPath() , _observableProxyStubPath() , _postMortemPath() + , _workerPoolSink(static_cast(THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT)) + , _callstackSink(static_cast(THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT)) + , _callstackDumpPath() , _pluginConfigPath() , _accessor() , _communicator() @@ -808,6 +836,17 @@ namespace PluginHost { _pluginConfigPath = Core::Directory::Normalize(config.Observe.PluginConfigPath.Value()); } _postMortemPath = Core::Directory::Normalize(config.PostMortemPath.Value()); + _callstackDumpPath = config.PostMortemCallstackDumpPath.IsSet() + ? Core::Directory::Normalize(config.PostMortemCallstackDumpPath.Value()) + : _postMortemPath; + _workerPoolSink = config.PostMortemWorkerPoolSink.IsSet() + ? ParsePostMortemDataSink(config.PostMortemWorkerPoolSink.Value(), + PostMortemDataSink::FILE) + : static_cast(THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT); + _callstackSink = config.PostMortemCallstackSink.IsSet() + ? ParsePostMortemDataSink(config.PostMortemCallstackSink.Value(), + PostMortemDataSink::DISABLED) + : static_cast(THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT); _appPath = Core::Directory::Normalize(Core::File::PathName(Core::ProcessInfo().Executable())); _hashKey = config.Signature.Value(); _communicator = Core::NodeId(config.Communicator.Value().c_str()); @@ -1039,6 +1078,18 @@ namespace PluginHost { { return (_postMortemPath); } + inline PostMortemDataSink PostMortemWorkerPoolSink() const + { + return (_workerPoolSink); + } + inline PostMortemDataSink PostMortemCallstackSink() const + { + return (_callstackSink); + } + inline const string& PostMortemCallstackDumpPath() const + { + return (_callstackDumpPath); + } inline bool PostMortemAllowed(PluginHost::IShell::reason why) const { std::list::const_iterator index(std::find(_reasons.begin(), _reasons.end(), why)); @@ -1334,6 +1385,9 @@ namespace PluginHost { string _proxyStubPath; string _observableProxyStubPath; string _postMortemPath; + PostMortemDataSink _workerPoolSink; + PostMortemDataSink _callstackSink; + string _callstackDumpPath; string _pluginConfigPath; Core::NodeId _accessor; Core::NodeId _communicator; diff --git a/Source/Thunder/GenericConfig.cmake b/Source/Thunder/GenericConfig.cmake index 16d00588b..3f6aa3a09 100644 --- a/Source/Thunder/GenericConfig.cmake +++ b/Source/Thunder/GenericConfig.cmake @@ -31,6 +31,7 @@ set(WEBSERVER_PATH "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/www/html" CACHE PATH "Ro set(WEBSERVER_PORT 8080 CACHE STRING "Port for the HTTP server") set(PROXYSTUB_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/${NAMESPACE_LIB}/proxystubs" CACHE PATH "Proxy stub path") set(POSTMORTEM_PATH "/opt/minidumps" CACHE PATH "Core file path to do the postmortem of the crash") +set(POSTMORTEM_CALLSTACK_DUMP_PATH "${POSTMORTEM_PATH}" CACHE PATH "Path for callstack dump file (defaults to POSTMORTEM_PATH)") set(MESSAGECONTROL_PATH "MessageDispatcher" CACHE STRING "MessageControl base path to create message files") set(MESSAGING_PORT 0 CACHE STRING "The port for the messaging") set(MESSAGING_STDOUT false CACHE STRING "Enable message rederict from stdout") @@ -89,6 +90,9 @@ map_set(${CONFIG} systempath ${SYSTEM_PATH}) map_set(${CONFIG} extensionpath ${EXTENSION_PATH}) map_set(${CONFIG} proxystubpath ${PROXYSTUB_PATH}) map_set(${CONFIG} postmortempath ${POSTMORTEM_PATH}) +map_set(${CONFIG} postmortemworkerpoolsink ${POSTMORTEM_WORKERPOOL_SINK}) +map_set(${CONFIG} postmortemcallstacksink ${POSTMORTEM_CALLSTACK_SINK}) +map_set(${CONFIG} postmortemcallstackdumppath ${POSTMORTEM_CALLSTACK_DUMP_PATH}) map_set(${CONFIG} redirect "/Service/Controller/UI/index.html") map_set(${CONFIG} ethernetcard ${ETHERNETCARD_NAME}) if(NOT COMMUNICATOR STREQUAL "") diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index b1c02d79c..ae0fec92f 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -5694,15 +5694,29 @@ namespace PluginHost { Core::JSON::ArrayType::Iterator index(data.WorkerPool.ThreadPoolRuns.Elements()); + const PluginHost::PostMortemDataSink wpSink = _config.PostMortemWorkerPoolSink(); + const PluginHost::PostMortemDataSink csSink = _config.PostMortemCallstackSink(); + while (index.Next() == true) { + const uint64_t threadIdRaw = index.Current().Id.Value(); + std::list stackList; - if (index.Current().Id.Value() != 0) { - ::DumpCallStack(PluginHost::Metadata::ThreadId(index.Current().Id.Value()), stackList); + if (threadIdRaw != 0) { + ::DumpCallStack(PluginHost::Metadata::ThreadId(threadIdRaw), stackList); + } + + if (csSink == PluginHost::PostMortemDataSink::LOG || csSink == PluginHost::PostMortemDataSink::ALL) { + for (const Core::callstack_info& entry : stackList) { + const char* sym = entry.function.empty() ? "Unknown symbol" : entry.function.c_str(); + fprintf(stderr, "[%s]:[%s]:[%d]:[%p]\n", + entry.module.c_str(), sym, entry.line, entry.address); + } + fflush(stderr); } PostMortemData::Callstack dump; - dump.Id = index.Current().Id.Value(); + dump.Id = threadIdRaw; for (const Core::callstack_info& info : stackList) { dump.Data.Add() = CallstackData(info); @@ -5711,13 +5725,26 @@ namespace PluginHost { data.Callstacks.Add(dump); } + if (csSink == PluginHost::PostMortemDataSink::FILE || csSink == PluginHost::PostMortemDataSink::ALL) { + DumpReadableMetadata(data, _config.PostMortemCallstackDumpPath()); + } + // Drop the workerpool info (what is currently running and what is pending) to a file.. - Core::File dumpFile(_config.PostMortemPath() + "ThunderInternals.json"); - if (dumpFile.Create(false) == true) { - data.IElement::ToFile(dumpFile); + if (wpSink == PluginHost::PostMortemDataSink::FILE || wpSink == PluginHost::PostMortemDataSink::ALL) { + Core::File dumpFile(_config.PostMortemPath() + "ThunderInternals.json"); + if (dumpFile.Create(false) == true) { + data.IElement::ToFile(dumpFile); + } } - DumpReadableMetadata(data); + if (wpSink == PluginHost::PostMortemDataSink::LOG || wpSink == PluginHost::PostMortemDataSink::ALL) { + string jsonContent; + data.IElement::ToString(jsonContent); + SYSLOG(Logging::Shutdown, (_T("WorkerPool snapshot start\n"))); + SYSLOG(Logging::Shutdown, (_T("[%s]\n"), jsonContent.c_str())); + SYSLOG(Logging::Shutdown, (_T("WorkerPool snapshot end\n"))); + fflush(stderr); + } } inline ServiceMap& Services() { @@ -5797,7 +5824,7 @@ namespace PluginHost { } private: - void DumpReadableMetadata(PostMortemData& data) const + void DumpReadableMetadata(PostMortemData& data, const string& outputPath) const { string readableDump; @@ -5874,7 +5901,7 @@ namespace PluginHost { appendReadableStack(index.Current()); } - Core::File readableDumpFile(_config.PostMortemPath() + "ThunderInternals.txt"); + Core::File readableDumpFile(outputPath + "ThunderInternals.txt"); if (readableDumpFile.Create(false) == true) { const uint32_t dumpSize = static_cast(readableDump.length() * sizeof(string::value_type)); const uint32_t written = readableDumpFile.Write(reinterpret_cast(readableDump.c_str()), dumpSize); diff --git a/Source/Thunder/Thunder.conf.in b/Source/Thunder/Thunder.conf.in index 8d5af86bf..393dbfb39 100644 --- a/Source/Thunder/Thunder.conf.in +++ b/Source/Thunder/Thunder.conf.in @@ -12,6 +12,9 @@ systempath = '@SYSTEM_PATH@' extensionpath = '@EXTENSION_PATH@' proxystubpath = '@PROXYSTUB_PATH@' postmortempath = '@POSTMORTEM_PATH@' +postmortemworkerpoolsink = '@POSTMORTEM_WORKERPOOL_SINK@' +postmortemcallstacksink = '@POSTMORTEM_CALLSTACK_SINK@' +postmortemcallstackdumppath = '@POSTMORTEM_CALLSTACK_DUMP_PATH@' redirect = '/Service/Controller/UI/index.html' ethernetcard = '@ETHERNETCARD_NAME@' communicator = '@COMMUNICATOR@' diff --git a/Source/Thunder/params.config b/Source/Thunder/params.config index 57dad574b..0e839000b 100644 --- a/Source/Thunder/params.config +++ b/Source/Thunder/params.config @@ -13,6 +13,9 @@ systempath extensionpath proxystubpath postmortempath +postmortemworkerpoolsink +postmortemcallstacksink +postmortemcallstackdumppath redirect ethernetcard communicator From bdb087bcc6cdb7ef6db5e5657a3998a6ca3e08db Mon Sep 17 00:00:00 2001 From: SatheeshkumarG15 Date: Thu, 9 Jul 2026 11:10:04 +0530 Subject: [PATCH 2/8] Added missing postmortem sink defaults to thunder_test_support compile definitions --- Tests/test_support/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/test_support/CMakeLists.txt b/Tests/test_support/CMakeLists.txt index 29a8b9f4f..10966af06 100644 --- a/Tests/test_support/CMakeLists.txt +++ b/Tests/test_support/CMakeLists.txt @@ -43,6 +43,8 @@ target_compile_definitions(${TARGET} THREADPOOL_COUNT=${THREADPOOL_COUNT} DEFAULT_SYSTEM_PATH="${SYSTEM_PATH}" DEFAULT_PROXYSTUB_PATH="${PROXYSTUB_PATH}" + THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0 + THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3 ) target_compile_options(${TARGET} PRIVATE -Wno-psabi) From eed8051cab5f2609d040ad7e4299e078d66b1374 Mon Sep 17 00:00:00 2001 From: SatheeshkumarG15 Date: Thu, 9 Jul 2026 11:47:01 +0530 Subject: [PATCH 3/8] Modified bridge.vcxproj to fix ThunderOnWindows failure in the PR --- Source/Thunder/bridge.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Thunder/bridge.vcxproj b/Source/Thunder/bridge.vcxproj index f9a01c0b4..30a9ac681 100755 --- a/Source/Thunder/bridge.vcxproj +++ b/Source/Thunder/bridge.vcxproj @@ -119,7 +119,7 @@ true true true - APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h $(FrameworkPath)plugins;$(FrameworkPath);$(WindowsPath);$(WindowsPath)zlib;$(FrameworkPath)addons @@ -143,7 +143,7 @@ Level3 Disabled true - APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h $(FrameworkPath)plugins;$(FrameworkPath);$(WindowsPath);$(WindowsPath)zlib;$(FrameworkPath)addons @@ -165,7 +165,7 @@ Level3 Disabled true - APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h $(FrameworkPath)plugins;$(FrameworkPath);$(WindowsPath);$(WindowsPath)zlib;$(FrameworkPath)addons @@ -189,7 +189,7 @@ true true true - APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h $(FrameworkPath)plugins;$(FrameworkPath);$(WindowsPath);$(WindowsPath)zlib;$(FrameworkPath)addons From 854b4586cf6a2987046b2621017794d193a509e3 Mon Sep 17 00:00:00 2001 From: SatheeshkumarG15 Date: Thu, 9 Jul 2026 16:29:19 +0530 Subject: [PATCH 4/8] Addressed co-pilot's valid comments --- Source/Thunder/Config.h | 2 +- Source/Thunder/PluginServer.h | 6 ++---- docs/introduction/config.md | 3 +++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Thunder/Config.h b/Source/Thunder/Config.h index 730aa6bc3..bfac860f3 100644 --- a/Source/Thunder/Config.h +++ b/Source/Thunder/Config.h @@ -36,7 +36,7 @@ namespace PluginHost { static inline PostMortemDataSink ParsePostMortemDataSink(const string& input, PostMortemDataSink fallback) { string s(input); - std::transform(s.begin(), s.end(), s.begin(), ::tolower); + std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return static_cast(::tolower(c)); }); if (s == _T("log")) return PostMortemDataSink::LOG; else if (s == _T("all")) return PostMortemDataSink::ALL; else if (s == _T("disabled")) return PostMortemDataSink::DISABLED; diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index ae0fec92f..60e2d03c4 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -5709,10 +5709,9 @@ namespace PluginHost { if (csSink == PluginHost::PostMortemDataSink::LOG || csSink == PluginHost::PostMortemDataSink::ALL) { for (const Core::callstack_info& entry : stackList) { const char* sym = entry.function.empty() ? "Unknown symbol" : entry.function.c_str(); - fprintf(stderr, "[%s]:[%s]:[%d]:[%p]\n", - entry.module.c_str(), sym, entry.line, entry.address); + SYSLOG(Logging::Shutdown, (_T("[%s]:[%s]:[%u]:[%p]"), + entry.module.c_str(), sym, static_cast(entry.line), entry.address)); } - fflush(stderr); } PostMortemData::Callstack dump; @@ -5743,7 +5742,6 @@ namespace PluginHost { SYSLOG(Logging::Shutdown, (_T("WorkerPool snapshot start\n"))); SYSLOG(Logging::Shutdown, (_T("[%s]\n"), jsonContent.c_str())); SYSLOG(Logging::Shutdown, (_T("WorkerPool snapshot end\n"))); - fflush(stderr); } } inline ServiceMap& Services() diff --git a/docs/introduction/config.md b/docs/introduction/config.md index 83e1d5e73..b6dd944bb 100644 --- a/docs/introduction/config.md +++ b/docs/introduction/config.md @@ -31,6 +31,9 @@ This section documents the available options for Thunder. This is different from | volatilepath | Directory to store volatile temporary data.

Each plugin will have an associated directory underneath this corresponding to the callsign of the plugin | string | /tmp | /tmp/ | | proxystubpath | Directory to search for the generated proxy stub libraries | string | - | /usr/lib/thunder/proxystubs | | postmortempath | Directory to store debugging info (worker pool information, debug data) in the event of a plugin or server crash.

If breakpad is found during build, will store breakpad mindumps here | string | /opt/minidumps | /opt/minidumps | +| postmortemworkerpoolsink | Controls where the WorkerPool JSON snapshot is written on crash.

Allowed values: `FILE` (write ThunderInternals.json to `postmortempath`), `LOG` (emit via SYSLOG), `ALL` (both), `DISABLED` (skip) | string | FILE | FILE | +| postmortemcallstacksink | Controls where per-thread callstack output is written on crash.

Allowed values: `FILE` (write ThunderInternals.txt to `postmortemcallstackdumppath`), `LOG` (emit via SYSLOG), `ALL` (both), `DISABLED` (skip) | string | DISABLED | DISABLED | +| postmortemcallstackdumppath | Directory to store the human-readable callstack dump file (ThunderInternals.txt) when `postmortemcallstacksink` is `FILE` or `ALL`.

Defaults to the value of `postmortempath` if not set | string | Value of `postmortempath` | /opt/minidumps | | communicator | Socket to listen for COM-RPC messages. Can be a filesystem path on Linux for a Unix domain socket, or a TCP socket.

For unix sockets, the file permissions can be specified by adding a `|` followed by the numeric permissions | string | /tmp/communicator\|0777 | 127.0.0.1:4000 | | redirect | Redirect incoming HTTP requests to the root Thunder URL to this address (please note it must contain the resource that is required e.g. index.html ) | string | http://127.0.0.1/Service/Controller/UI/index.html | http://127.0.0.1/Service/Controller/UI/index.html | | idletime | Amount of time (in seconds) to wait before closing and cleaning up idle client connections. If no activity occurs over a connection for this time Thunder will close it. | integer | 180 | 180 | From 687a210793e9f251892e702cba49a29ae21912c8 Mon Sep 17 00:00:00 2001 From: SatheeshkumarG15 Date: Thu, 9 Jul 2026 17:10:37 +0530 Subject: [PATCH 5/8] Addressed few more co-pilot's comments --- Source/Thunder/PluginServer.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index 60e2d03c4..e59c60ad6 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -5697,6 +5697,10 @@ namespace PluginHost { const PluginHost::PostMortemDataSink wpSink = _config.PostMortemWorkerPoolSink(); const PluginHost::PostMortemDataSink csSink = _config.PostMortemCallstackSink(); + if ((wpSink == PluginHost::PostMortemDataSink::DISABLED) && (csSink == PluginHost::PostMortemDataSink::DISABLED)) { + return; + } + while (index.Next() == true) { const uint64_t threadIdRaw = index.Current().Id.Value(); From 92d8726168678eab93df37b3f82d7a5e4ec5553c Mon Sep 17 00:00:00 2001 From: SatheeshkumarG15 Date: Mon, 13 Jul 2026 12:32:04 +0530 Subject: [PATCH 6/8] Removed postmortemcallstacksinkpath to create all the postmortemsinks in a generic path i.e Postmortempath --- Source/Thunder/Config.h | 11 ----------- Source/Thunder/GenericConfig.cmake | 2 -- Source/Thunder/PluginServer.h | 2 +- Source/Thunder/Thunder.conf.in | 1 - Source/Thunder/params.config | 1 - docs/introduction/config.md | 3 +-- 6 files changed, 2 insertions(+), 18 deletions(-) diff --git a/Source/Thunder/Config.h b/Source/Thunder/Config.h index bfac860f3..fdeb800cd 100644 --- a/Source/Thunder/Config.h +++ b/Source/Thunder/Config.h @@ -480,7 +480,6 @@ namespace PluginHost { Add(_T("postmortempath"), &PostMortemPath); Add(_T("postmortemworkerpoolsink"), &PostMortemWorkerPoolSink); Add(_T("postmortemcallstacksink"), &PostMortemCallstackSink); - Add(_T("postmortemcallstackdumppath"), &PostMortemCallstackDumpPath); Add(_T("communicator"), &Communicator); Add(_T("signature"), &Signature); Add(_T("idletime"), &IdleTime); @@ -539,7 +538,6 @@ namespace PluginHost { Core::JSON::String PostMortemPath; Core::JSON::String PostMortemWorkerPoolSink; Core::JSON::String PostMortemCallstackSink; - Core::JSON::String PostMortemCallstackDumpPath; Core::JSON::String Communicator; Core::JSON::String Redirect; Core::JSON::String Signature; @@ -722,7 +720,6 @@ namespace PluginHost { , _postMortemPath() , _workerPoolSink(static_cast(THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT)) , _callstackSink(static_cast(THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT)) - , _callstackDumpPath() , _pluginConfigPath() , _accessor() , _communicator() @@ -836,9 +833,6 @@ namespace PluginHost { _pluginConfigPath = Core::Directory::Normalize(config.Observe.PluginConfigPath.Value()); } _postMortemPath = Core::Directory::Normalize(config.PostMortemPath.Value()); - _callstackDumpPath = config.PostMortemCallstackDumpPath.IsSet() - ? Core::Directory::Normalize(config.PostMortemCallstackDumpPath.Value()) - : _postMortemPath; _workerPoolSink = config.PostMortemWorkerPoolSink.IsSet() ? ParsePostMortemDataSink(config.PostMortemWorkerPoolSink.Value(), PostMortemDataSink::FILE) @@ -1086,10 +1080,6 @@ namespace PluginHost { { return (_callstackSink); } - inline const string& PostMortemCallstackDumpPath() const - { - return (_callstackDumpPath); - } inline bool PostMortemAllowed(PluginHost::IShell::reason why) const { std::list::const_iterator index(std::find(_reasons.begin(), _reasons.end(), why)); @@ -1387,7 +1377,6 @@ namespace PluginHost { string _postMortemPath; PostMortemDataSink _workerPoolSink; PostMortemDataSink _callstackSink; - string _callstackDumpPath; string _pluginConfigPath; Core::NodeId _accessor; Core::NodeId _communicator; diff --git a/Source/Thunder/GenericConfig.cmake b/Source/Thunder/GenericConfig.cmake index 3f6aa3a09..641a8502c 100644 --- a/Source/Thunder/GenericConfig.cmake +++ b/Source/Thunder/GenericConfig.cmake @@ -31,7 +31,6 @@ set(WEBSERVER_PATH "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/www/html" CACHE PATH "Ro set(WEBSERVER_PORT 8080 CACHE STRING "Port for the HTTP server") set(PROXYSTUB_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/${NAMESPACE_LIB}/proxystubs" CACHE PATH "Proxy stub path") set(POSTMORTEM_PATH "/opt/minidumps" CACHE PATH "Core file path to do the postmortem of the crash") -set(POSTMORTEM_CALLSTACK_DUMP_PATH "${POSTMORTEM_PATH}" CACHE PATH "Path for callstack dump file (defaults to POSTMORTEM_PATH)") set(MESSAGECONTROL_PATH "MessageDispatcher" CACHE STRING "MessageControl base path to create message files") set(MESSAGING_PORT 0 CACHE STRING "The port for the messaging") set(MESSAGING_STDOUT false CACHE STRING "Enable message rederict from stdout") @@ -92,7 +91,6 @@ map_set(${CONFIG} proxystubpath ${PROXYSTUB_PATH}) map_set(${CONFIG} postmortempath ${POSTMORTEM_PATH}) map_set(${CONFIG} postmortemworkerpoolsink ${POSTMORTEM_WORKERPOOL_SINK}) map_set(${CONFIG} postmortemcallstacksink ${POSTMORTEM_CALLSTACK_SINK}) -map_set(${CONFIG} postmortemcallstackdumppath ${POSTMORTEM_CALLSTACK_DUMP_PATH}) map_set(${CONFIG} redirect "/Service/Controller/UI/index.html") map_set(${CONFIG} ethernetcard ${ETHERNETCARD_NAME}) if(NOT COMMUNICATOR STREQUAL "") diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index e59c60ad6..bdbbff4b6 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -5729,7 +5729,7 @@ namespace PluginHost { } if (csSink == PluginHost::PostMortemDataSink::FILE || csSink == PluginHost::PostMortemDataSink::ALL) { - DumpReadableMetadata(data, _config.PostMortemCallstackDumpPath()); + DumpReadableMetadata(data, _config.PostMortemPath()); } // Drop the workerpool info (what is currently running and what is pending) to a file.. diff --git a/Source/Thunder/Thunder.conf.in b/Source/Thunder/Thunder.conf.in index 393dbfb39..59c342815 100644 --- a/Source/Thunder/Thunder.conf.in +++ b/Source/Thunder/Thunder.conf.in @@ -14,7 +14,6 @@ proxystubpath = '@PROXYSTUB_PATH@' postmortempath = '@POSTMORTEM_PATH@' postmortemworkerpoolsink = '@POSTMORTEM_WORKERPOOL_SINK@' postmortemcallstacksink = '@POSTMORTEM_CALLSTACK_SINK@' -postmortemcallstackdumppath = '@POSTMORTEM_CALLSTACK_DUMP_PATH@' redirect = '/Service/Controller/UI/index.html' ethernetcard = '@ETHERNETCARD_NAME@' communicator = '@COMMUNICATOR@' diff --git a/Source/Thunder/params.config b/Source/Thunder/params.config index 0e839000b..4342a9ea8 100644 --- a/Source/Thunder/params.config +++ b/Source/Thunder/params.config @@ -15,7 +15,6 @@ proxystubpath postmortempath postmortemworkerpoolsink postmortemcallstacksink -postmortemcallstackdumppath redirect ethernetcard communicator diff --git a/docs/introduction/config.md b/docs/introduction/config.md index b6dd944bb..a7522f561 100644 --- a/docs/introduction/config.md +++ b/docs/introduction/config.md @@ -32,8 +32,7 @@ This section documents the available options for Thunder. This is different from | proxystubpath | Directory to search for the generated proxy stub libraries | string | - | /usr/lib/thunder/proxystubs | | postmortempath | Directory to store debugging info (worker pool information, debug data) in the event of a plugin or server crash.

If breakpad is found during build, will store breakpad mindumps here | string | /opt/minidumps | /opt/minidumps | | postmortemworkerpoolsink | Controls where the WorkerPool JSON snapshot is written on crash.

Allowed values: `FILE` (write ThunderInternals.json to `postmortempath`), `LOG` (emit via SYSLOG), `ALL` (both), `DISABLED` (skip) | string | FILE | FILE | -| postmortemcallstacksink | Controls where per-thread callstack output is written on crash.

Allowed values: `FILE` (write ThunderInternals.txt to `postmortemcallstackdumppath`), `LOG` (emit via SYSLOG), `ALL` (both), `DISABLED` (skip) | string | DISABLED | DISABLED | -| postmortemcallstackdumppath | Directory to store the human-readable callstack dump file (ThunderInternals.txt) when `postmortemcallstacksink` is `FILE` or `ALL`.

Defaults to the value of `postmortempath` if not set | string | Value of `postmortempath` | /opt/minidumps | +| postmortemcallstacksink | Controls where per-thread callstack output is written on crash.

Allowed values: `FILE` (write ThunderInternals.txt to `postmortempath`), `LOG` (emit via SYSLOG), `ALL` (both), `DISABLED` (skip) | string | DISABLED | DISABLED | | communicator | Socket to listen for COM-RPC messages. Can be a filesystem path on Linux for a Unix domain socket, or a TCP socket.

For unix sockets, the file permissions can be specified by adding a `|` followed by the numeric permissions | string | /tmp/communicator\|0777 | 127.0.0.1:4000 | | redirect | Redirect incoming HTTP requests to the root Thunder URL to this address (please note it must contain the resource that is required e.g. index.html ) | string | http://127.0.0.1/Service/Controller/UI/index.html | http://127.0.0.1/Service/Controller/UI/index.html | | idletime | Amount of time (in seconds) to wait before closing and cleaning up idle client connections. If no activity occurs over a connection for this time Thunder will close it. | integer | 180 | 180 | From 981a9740279c2aa6ce4fff6a543d5abb5bf76fb2 Mon Sep 17 00:00:00 2001 From: SatheeshkumarG15 Date: Mon, 13 Jul 2026 18:08:23 +0530 Subject: [PATCH 7/8] Addressed reviewer's comment and updated to Core::JSON::EnumType --- Source/Thunder/CMakeLists.txt | 6 +-- Source/Thunder/Config.h | 29 ++++-------- Source/Thunder/PluginServer.cpp | 9 ++++ Source/Thunder/PluginServer.h | 73 +++++++++++++++---------------- Source/Thunder/bridge.vcxproj | 8 ++-- Tests/test_support/CMakeLists.txt | 4 +- 6 files changed, 62 insertions(+), 67 deletions(-) diff --git a/Source/Thunder/CMakeLists.txt b/Source/Thunder/CMakeLists.txt index 5589abb1d..88d241a01 100644 --- a/Source/Thunder/CMakeLists.txt +++ b/Source/Thunder/CMakeLists.txt @@ -24,11 +24,11 @@ set(ENABLE_TRACING_MODULES "" CACHE STRING "A space separated list of specific macro(thunder_postmortem_sink_value VAR_IN VAR_OUT) string(TOUPPER "${${VAR_IN}}" _s) - if (_s STREQUAL "LOG") + if (_s STREQUAL "FILE") set(${VAR_OUT} 1) - elseif(_s STREQUAL "ALL") + elseif(_s STREQUAL "LOG") set(${VAR_OUT} 2) - elseif(_s STREQUAL "DISABLED") + elseif(_s STREQUAL "ALL") set(${VAR_OUT} 3) else() set(${VAR_OUT} 0) diff --git a/Source/Thunder/Config.h b/Source/Thunder/Config.h index fdeb800cd..9c69954b4 100644 --- a/Source/Thunder/Config.h +++ b/Source/Thunder/Config.h @@ -27,23 +27,12 @@ namespace Thunder { namespace PluginHost { enum class PostMortemDataSink : uint8_t { - FILE = 0, - LOG = 1, - ALL = 2, - DISABLED = 3 + DISABLED = 0, + FILE = 1, + LOG = 2, + ALL = 3 }; - static inline PostMortemDataSink ParsePostMortemDataSink(const string& input, PostMortemDataSink fallback) - { - string s(input); - std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return static_cast(::tolower(c)); }); - if (s == _T("log")) return PostMortemDataSink::LOG; - else if (s == _T("all")) return PostMortemDataSink::ALL; - else if (s == _T("disabled")) return PostMortemDataSink::DISABLED; - else if (s == _T("file")) return PostMortemDataSink::FILE; - return fallback; - } - /** * IMPORTANT: If updating this class to add/remove/modify configuration options, ensure * the documentation in docs/introduction/config.md is updated to reflect the changes! @@ -536,8 +525,8 @@ namespace PluginHost { Core::JSON::String VolatilePath; Core::JSON::String ProxyStubPath; Core::JSON::String PostMortemPath; - Core::JSON::String PostMortemWorkerPoolSink; - Core::JSON::String PostMortemCallstackSink; + Core::JSON::EnumType PostMortemWorkerPoolSink; + Core::JSON::EnumType PostMortemCallstackSink; Core::JSON::String Communicator; Core::JSON::String Redirect; Core::JSON::String Signature; @@ -834,12 +823,10 @@ namespace PluginHost { } _postMortemPath = Core::Directory::Normalize(config.PostMortemPath.Value()); _workerPoolSink = config.PostMortemWorkerPoolSink.IsSet() - ? ParsePostMortemDataSink(config.PostMortemWorkerPoolSink.Value(), - PostMortemDataSink::FILE) + ? config.PostMortemWorkerPoolSink.Value() : static_cast(THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT); _callstackSink = config.PostMortemCallstackSink.IsSet() - ? ParsePostMortemDataSink(config.PostMortemCallstackSink.Value(), - PostMortemDataSink::DISABLED) + ? config.PostMortemCallstackSink.Value() : static_cast(THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT); _appPath = Core::Directory::Normalize(Core::File::PathName(Core::ProcessInfo().Executable())); _hashKey = config.Signature.Value(); diff --git a/Source/Thunder/PluginServer.cpp b/Source/Thunder/PluginServer.cpp index b87ca88d1..c483d51cb 100644 --- a/Source/Thunder/PluginServer.cpp +++ b/Source/Thunder/PluginServer.cpp @@ -51,6 +51,15 @@ ENUM_CONVERSION_BEGIN(PluginHost::InputHandler::type) ENUM_CONVERSION_END(PluginHost::InputHandler::type) +ENUM_CONVERSION_BEGIN(PluginHost::PostMortemDataSink) + + { PluginHost::PostMortemDataSink::DISABLED, _TXT("Disabled") }, + { PluginHost::PostMortemDataSink::FILE, _TXT("File") }, + { PluginHost::PostMortemDataSink::LOG, _TXT("Log") }, + { PluginHost::PostMortemDataSink::ALL, _TXT("All") }, + +ENUM_CONVERSION_END(PluginHost::PostMortemDataSink) + namespace PluginHost { // // STATIC declarations diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index bdbbff4b6..16c414eb6 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -5697,55 +5697,54 @@ namespace PluginHost { const PluginHost::PostMortemDataSink wpSink = _config.PostMortemWorkerPoolSink(); const PluginHost::PostMortemDataSink csSink = _config.PostMortemCallstackSink(); - if ((wpSink == PluginHost::PostMortemDataSink::DISABLED) && (csSink == PluginHost::PostMortemDataSink::DISABLED)) { - return; - } + if ((wpSink != PluginHost::PostMortemDataSink::DISABLED) || (csSink != PluginHost::PostMortemDataSink::DISABLED)) { - while (index.Next() == true) { + while (index.Next() == true) { - const uint64_t threadIdRaw = index.Current().Id.Value(); + const uint64_t threadIdRaw = index.Current().Id.Value(); - std::list stackList; - if (threadIdRaw != 0) { - ::DumpCallStack(PluginHost::Metadata::ThreadId(threadIdRaw), stackList); - } + std::list stackList; + if (threadIdRaw != 0) { + ::DumpCallStack(PluginHost::Metadata::ThreadId(threadIdRaw), stackList); + } - if (csSink == PluginHost::PostMortemDataSink::LOG || csSink == PluginHost::PostMortemDataSink::ALL) { - for (const Core::callstack_info& entry : stackList) { - const char* sym = entry.function.empty() ? "Unknown symbol" : entry.function.c_str(); - SYSLOG(Logging::Shutdown, (_T("[%s]:[%s]:[%u]:[%p]"), - entry.module.c_str(), sym, static_cast(entry.line), entry.address)); + if (csSink == PluginHost::PostMortemDataSink::LOG || csSink == PluginHost::PostMortemDataSink::ALL) { + for (const Core::callstack_info& entry : stackList) { + const char* sym = entry.function.empty() ? "Unknown symbol" : entry.function.c_str(); + SYSLOG(Logging::Shutdown, (_T("[%s]:[%s]:[%u]:[%p]"), + entry.module.c_str(), sym, static_cast(entry.line), entry.address)); + } } - } - PostMortemData::Callstack dump; - dump.Id = threadIdRaw; + PostMortemData::Callstack dump; + dump.Id = threadIdRaw; - for (const Core::callstack_info& info : stackList) { - dump.Data.Add() = CallstackData(info); - } + for (const Core::callstack_info& info : stackList) { + dump.Data.Add() = CallstackData(info); + } - data.Callstacks.Add(dump); - } + data.Callstacks.Add(dump); + } - if (csSink == PluginHost::PostMortemDataSink::FILE || csSink == PluginHost::PostMortemDataSink::ALL) { - DumpReadableMetadata(data, _config.PostMortemPath()); - } + if (csSink == PluginHost::PostMortemDataSink::FILE || csSink == PluginHost::PostMortemDataSink::ALL) { + DumpReadableMetadata(data, _config.PostMortemPath()); + } - // Drop the workerpool info (what is currently running and what is pending) to a file.. - if (wpSink == PluginHost::PostMortemDataSink::FILE || wpSink == PluginHost::PostMortemDataSink::ALL) { - Core::File dumpFile(_config.PostMortemPath() + "ThunderInternals.json"); - if (dumpFile.Create(false) == true) { - data.IElement::ToFile(dumpFile); + // Drop the workerpool info (what is currently running and what is pending) to a file.. + if (wpSink == PluginHost::PostMortemDataSink::FILE || wpSink == PluginHost::PostMortemDataSink::ALL) { + Core::File dumpFile(_config.PostMortemPath() + "ThunderInternals.json"); + if (dumpFile.Create(false) == true) { + data.IElement::ToFile(dumpFile); + } } - } - if (wpSink == PluginHost::PostMortemDataSink::LOG || wpSink == PluginHost::PostMortemDataSink::ALL) { - string jsonContent; - data.IElement::ToString(jsonContent); - SYSLOG(Logging::Shutdown, (_T("WorkerPool snapshot start\n"))); - SYSLOG(Logging::Shutdown, (_T("[%s]\n"), jsonContent.c_str())); - SYSLOG(Logging::Shutdown, (_T("WorkerPool snapshot end\n"))); + if (wpSink == PluginHost::PostMortemDataSink::LOG || wpSink == PluginHost::PostMortemDataSink::ALL) { + string jsonContent; + data.IElement::ToString(jsonContent); + SYSLOG(Logging::Shutdown, (_T("WorkerPool snapshot start\n"))); + SYSLOG(Logging::Shutdown, (_T("[%s]\n"), jsonContent.c_str())); + SYSLOG(Logging::Shutdown, (_T("WorkerPool snapshot end\n"))); + } } } inline ServiceMap& Services() diff --git a/Source/Thunder/bridge.vcxproj b/Source/Thunder/bridge.vcxproj index 30a9ac681..71770e921 100755 --- a/Source/Thunder/bridge.vcxproj +++ b/Source/Thunder/bridge.vcxproj @@ -119,7 +119,7 @@ true true true - APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=1;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=0;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h $(FrameworkPath)plugins;$(FrameworkPath);$(WindowsPath);$(WindowsPath)zlib;$(FrameworkPath)addons @@ -143,7 +143,7 @@ Level3 Disabled true - APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=1;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=0;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h $(FrameworkPath)plugins;$(FrameworkPath);$(WindowsPath);$(WindowsPath)zlib;$(FrameworkPath)addons @@ -165,7 +165,7 @@ Level3 Disabled true - APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=1;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h $(FrameworkPath)plugins;$(FrameworkPath);$(WindowsPath);$(WindowsPath)zlib;$(FrameworkPath)addons @@ -189,7 +189,7 @@ true true true - APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + APPLICATION_NAME=Thunder;__CORE_MESSAGING__;_CRT_SECURE_NO_WARNINGS;_WINDOWS;THREADPOOL_COUNT=4;HOSTING_COMPROCESS=comprocess.exe;THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=1;THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=0;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true pch.h $(FrameworkPath)plugins;$(FrameworkPath);$(WindowsPath);$(WindowsPath)zlib;$(FrameworkPath)addons diff --git a/Tests/test_support/CMakeLists.txt b/Tests/test_support/CMakeLists.txt index 10966af06..8f6a87bf2 100644 --- a/Tests/test_support/CMakeLists.txt +++ b/Tests/test_support/CMakeLists.txt @@ -43,8 +43,8 @@ target_compile_definitions(${TARGET} THREADPOOL_COUNT=${THREADPOOL_COUNT} DEFAULT_SYSTEM_PATH="${SYSTEM_PATH}" DEFAULT_PROXYSTUB_PATH="${PROXYSTUB_PATH}" - THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=0 - THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=3 + THUNDER_POSTMORTEM_WORKERPOOL_SINK_DEFAULT=1 + THUNDER_POSTMORTEM_CALLSTACK_SINK_DEFAULT=0 ) target_compile_options(${TARGET} PRIVATE -Wno-psabi) From 32d8fc036ee770c2576500d874dc9a5daf8e021d Mon Sep 17 00:00:00 2001 From: SatheeshkumarG15 Date: Mon, 13 Jul 2026 18:19:45 +0530 Subject: [PATCH 8/8] Addressed co-pilot comments --- Source/Thunder/PluginServer.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index 16c414eb6..709da94e9 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -5689,16 +5689,16 @@ namespace PluginHost { return (_connections.Connection(id)); } inline void DumpMetadata() { - PostMortemData data; - _dispatcher.Snapshot(data.WorkerPool); - - Core::JSON::ArrayType::Iterator index(data.WorkerPool.ThreadPoolRuns.Elements()); - const PluginHost::PostMortemDataSink wpSink = _config.PostMortemWorkerPoolSink(); const PluginHost::PostMortemDataSink csSink = _config.PostMortemCallstackSink(); if ((wpSink != PluginHost::PostMortemDataSink::DISABLED) || (csSink != PluginHost::PostMortemDataSink::DISABLED)) { + PostMortemData data; + _dispatcher.Snapshot(data.WorkerPool); + + Core::JSON::ArrayType::Iterator index(data.WorkerPool.ThreadPoolRuns.Elements()); + while (index.Next() == true) { const uint64_t threadIdRaw = index.Current().Id.Value();