From 46e6ed314c86422099098b44a4b5a1e2fc3ba10d Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Fri, 22 Mar 2024 18:22:57 +0100 Subject: [PATCH 01/15] SILKIT-1477 SystemController Utility: Improve messages for certain scenarios --- .../SystemController.cpp | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/Utilities/SilKitSystemController/SystemController.cpp b/Utilities/SilKitSystemController/SystemController.cpp index 1071505c2..537632323 100644 --- a/Utilities/SilKitSystemController/SystemController.cpp +++ b/Utilities/SilKitSystemController/SystemController.cpp @@ -68,6 +68,26 @@ class SilKitController _monitor = participant->CreateSystemMonitor(); _logger = participant->GetLogger(); + _monitor->SetParticipantConnectedHandler( + [this](const ParticipantConnectionInformation& participantInformation) { + std::ostringstream ss; + ss << "Participant '" << participantInformation.participantName << "' joined the simulation"; + LogInfo(ss.str()); + }); + _monitor->AddSystemStateHandler([&](const SystemState& systemState) { + if (systemState == SystemState::Stopping) + { + if (!_isStopRequested) + { + LogInfo("An external event causes the simulation to stop"); + } + } + else if (systemState == SystemState::Error) + { + LogInfo("SIL Kit simulation is in error state"); + } + }); + _lifecycleService = participant->CreateLifecycleService({SilKit::Services::Orchestration::OperationMode::Coordinated}); _finalStatePromise = _lifecycleService->StartLifecycle(); @@ -75,9 +95,10 @@ class SilKitController void StopOrAbort() { + _isStopRequested = true; if (_monitor->SystemState() == SystemState::Running || _monitor->SystemState() == SystemState::Paused) { - LogInfo("Stopping the SIL Kit simulation..."); + LogInfo("System controller stops the SIL Kit simulation..."); _lifecycleService->Stop("Stop via interaction in sil-kit-system-controller"); } else if (_monitor->SystemState() == SystemState::Aborting) @@ -91,7 +112,11 @@ class SilKitController } else { - LogWarn("SIL Kit SystemState is invalid. Sending AbortSimulation..."); + { + std::ostringstream ss; + ss << "SIL Kit simulation is in state " << _monitor->SystemState() << " and cannot be stopped, attempting to abort..."; + LogInfo(ss.str()); + } _controller->AbortSimulation(); _aborted = true; } @@ -107,7 +132,7 @@ class SilKitController { if (_aborted) { - LogWarn("SIL Kit simulation shut down after AbortSimulation."); + LogWarn("SIL Kit simulation was shut down via abort signal"); } else if (_externalShutdown) { @@ -129,12 +154,12 @@ class SilKitController if (_aborted) { - LogWarn("SIL Kit simulation did not shut down after AbortSimulation. Terminating."); + LogWarn("SIL Kit simulation did not shut down via abort signal. Terminating..."); return; } else { - LogWarn("SIL Kit simulation did not shut down after Stop. Sending AbortSimulation..."); + LogWarn("SIL Kit simulation did not shut down via stop signal. Attempting to abort..."); _aborted = true; _controller->AbortSimulation(); WaitForFinalStateWithRetries(); @@ -171,6 +196,7 @@ class SilKitController std::shared_ptr _config; std::vector _expectedParticipantNames; + std::atomic _isStopRequested = false; bool _aborted = false; bool _externalShutdown = false; SilKit::Experimental::Services::Orchestration::ISystemController* _controller; @@ -365,7 +391,7 @@ int main(int argc, char** argv) } else { - std::cout << "Press enter to stop the SIL Kit simulation..." << std::endl; + std::cout << "Press enter to end the simulation..." << std::endl; std::cin.ignore(); controller.StopOrAbort(); @@ -375,7 +401,7 @@ int main(int argc, char** argv) catch (const std::exception& error) { std::cerr << "Something went wrong: " << error.what() << std::endl; - std::cout << "Press enter to stop the process..." << std::endl; + std::cout << "Press enter to end the process..." << std::endl; std::cin.ignore(); return -3; From f727e1ba232274a2974725cb5c04075a8118a0fd Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Fri, 22 Mar 2024 18:24:39 +0100 Subject: [PATCH 02/15] SILKIT-1477 SystemController Utility: Improve messages for certain scenarios * Leaner messages: "SIL Kit simulation" => "simulation" --- .../SystemController.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Utilities/SilKitSystemController/SystemController.cpp b/Utilities/SilKitSystemController/SystemController.cpp index 537632323..1d70b2d93 100644 --- a/Utilities/SilKitSystemController/SystemController.cpp +++ b/Utilities/SilKitSystemController/SystemController.cpp @@ -84,7 +84,7 @@ class SilKitController } else if (systemState == SystemState::Error) { - LogInfo("SIL Kit simulation is in error state"); + LogInfo("Simulation is in error state"); } }); @@ -98,12 +98,12 @@ class SilKitController _isStopRequested = true; if (_monitor->SystemState() == SystemState::Running || _monitor->SystemState() == SystemState::Paused) { - LogInfo("System controller stops the SIL Kit simulation..."); + LogInfo("System controller stops the simulation..."); _lifecycleService->Stop("Stop via interaction in sil-kit-system-controller"); } else if (_monitor->SystemState() == SystemState::Aborting) { - LogWarn("SIL Kit simulation is already aborting..."); + LogWarn("Simulation is already aborting..."); _aborted = true; } else if (_monitor->SystemState() == SystemState::Shutdown) @@ -114,7 +114,7 @@ class SilKitController { { std::ostringstream ss; - ss << "SIL Kit simulation is in state " << _monitor->SystemState() << " and cannot be stopped, attempting to abort..."; + ss << "Simulation is in state " << _monitor->SystemState() << " and cannot be stopped, attempting to abort..."; LogInfo(ss.str()); } _controller->AbortSimulation(); @@ -132,34 +132,34 @@ class SilKitController { if (_aborted) { - LogWarn("SIL Kit simulation was shut down via abort signal"); + LogWarn("Simulation was shut down via abort signal"); } else if (_externalShutdown) { - LogInfo("SIL Kit simulation was shut down externally."); + LogInfo("Simulation was shut down externally."); } else { - LogInfo("SIL Kit simulation shut down."); + LogInfo("Simulation shut down."); } return; } else { std::ostringstream ss; - ss << "SIL Kit simulation did not shut down in 5s... Retry " << retries << "/" << numRetries; + ss << "Simulation did not shut down in 5s... Retry " << retries << "/" << numRetries; LogWarn(ss.str()); } } if (_aborted) { - LogWarn("SIL Kit simulation did not shut down via abort signal. Terminating..."); + LogWarn("Simulation did not shut down via abort signal. Terminating..."); return; } else { - LogWarn("SIL Kit simulation did not shut down via stop signal. Attempting to abort..."); + LogWarn("Simulation did not shut down via stop signal. Attempting to abort..."); _aborted = true; _controller->AbortSimulation(); WaitForFinalStateWithRetries(); @@ -171,7 +171,7 @@ class SilKitController ParticipantState state = _finalStatePromise.get(); if (state == ParticipantState::Shutdown) { - LogInfo("SIL Kit simulation was shut down externally."); + LogInfo("Simulation was shut down externally."); } else { From aa0b2c0647a1f27f7fbe1162d8784b9cb8f6ab43 Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Wed, 27 Mar 2024 23:49:06 +0100 Subject: [PATCH 03/15] SILKIT-1477 SystemController Utility: Replace interactive mode with SigInt handler --- .../SystemController.cpp | 97 +++++++++++++------ docs/CHANGELOG.rst | 7 ++ 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/Utilities/SilKitSystemController/SystemController.cpp b/Utilities/SilKitSystemController/SystemController.cpp index 1d70b2d93..19647f7e1 100644 --- a/Utilities/SilKitSystemController/SystemController.cpp +++ b/Utilities/SilKitSystemController/SystemController.cpp @@ -54,6 +54,62 @@ std::ostream& operator<<(std::ostream& out, std::chrono::nanoseconds timestamp) namespace { +std::function signalInterruptHandler; + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + +#include + +BOOL WINAPI HandleSignal(_In_ DWORD dwCtrlType) +{ + if (dwCtrlType == CTRL_C_EVENT) + { + signalInterruptHandler(); + } + return FALSE; +} + +void ConfigureSignalInterruptHandler(std::function handler) +{ + signalInterruptHandler = handler; + + if (SetConsoleCtrlHandler(HandleSignal, TRUE) == FALSE) + { + throw std::runtime_error("Failed to install OS signal handler"); + } +} + +#elif defined(linux) || defined(__linux) || defined(__linux__) || \ + defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + +#include + +void HandleSignal(int signum) +{ + if (signum == SIGINT) + { + signalHandler(); + } +} + +void ConfigureSignalInterruptHandler(std::function handler) +{ + signalInterruptHandler = handler; + + struct sigaction action; + action.sa_handler = &HandleSignal; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + if (sigaction(SIGINT, &action, nullptr) != 0) + { + throw std::runtime_error("Failed to install OS signal handler"); + } +} + +#else +#error Unsupported operating system +#endif + class SilKitController { public: @@ -80,6 +136,7 @@ class SilKitController if (!_isStopRequested) { LogInfo("An external event causes the simulation to stop"); + fclose(stdin); } } else if (systemState == SystemState::Error) @@ -96,6 +153,7 @@ class SilKitController void StopOrAbort() { _isStopRequested = true; + LogInfo("User requested to stop"); if (_monitor->SystemState() == SystemState::Running || _monitor->SystemState() == SystemState::Paused) { LogInfo("System controller stops the simulation..."); @@ -132,15 +190,15 @@ class SilKitController { if (_aborted) { - LogWarn("Simulation was shut down via abort signal"); + LogWarn("Simulation was shut down by user request via abort signal"); } else if (_externalShutdown) { - LogInfo("Simulation was shut down externally."); + LogInfo("Simulation was shut down externally"); } else { - LogInfo("Simulation shut down."); + LogInfo("Simulation was shut down by user request"); } return; } @@ -171,7 +229,7 @@ class SilKitController ParticipantState state = _finalStatePromise.get(); if (state == ParticipantState::Shutdown) { - LogInfo("Simulation was shut down externally."); + LogInfo("Simulation was shut down externally"); } else { @@ -234,9 +292,6 @@ int main(int argc, char** argv) CommandlineParser commandlineParser; commandlineParser.Add("version", "v", "[--version]", "-v, --version: Get version info."); commandlineParser.Add("help", "h", "[--help]", "-h, --help: Get this help."); - commandlineParser.Add( - "non-interactive", "ni", "[--non-interactive]", - "--non-interactive: Run without awaiting any user interactions at any time."); commandlineParser.Add( "connect-uri", "u", "silkit://localhost:8500", "[--connect-uri ]", "-u, --connect-uri : The registry URI to connect to. Defaults to 'silkit://localhost:8500'."); @@ -352,19 +407,13 @@ int main(int argc, char** argv) { std::cerr << "Error: Failed to load configuration '" << configurationFilename << "', " << error.what() << std::endl; - std::cout << "Press enter to stop the process..." << std::endl; - std::cin.ignore(); return -2; } try { - std::cout << "Creating participant '" << participantName << "' with registry " << connectUri - << ", expecting participant" << (expectedParticipantNames.size() > 1 ? "s '" : " '"); - std::copy(expectedParticipantNames.begin(), std::prev(expectedParticipantNames.end()), - std::ostream_iterator(std::cout, "', '")); - std::cout << expectedParticipantNames.back() << "'..." << std::endl; + std::cout << "Creating participant '" << participantName << "' with registry " << connectUri << std::endl; auto participant = SilKit::CreateParticipant(configuration, participantName, connectUri); @@ -382,27 +431,17 @@ int main(int argc, char** argv) expectedParticipantNames.push_back(participantName); SilKitController controller(participant.get(), configuration, expectedParticipantNames); - bool nonInteractiveMode = - (commandlineParser.Get("non-interactive").Value()) ? true : false; - - if (nonInteractiveMode) - { - controller.WaitForExternalShutdown(); - } - else - { - std::cout << "Press enter to end the simulation..." << std::endl; - std::cin.ignore(); - + std::cout << "Press Ctrl-C to end the simulation..." << std::endl; + ConfigureSignalInterruptHandler([&]() { controller.StopOrAbort(); controller.WaitForFinalStateWithRetries(); - } + }); + + controller.WaitForExternalShutdown(); } catch (const std::exception& error) { std::cerr << "Something went wrong: " << error.what() << std::endl; - std::cout << "Press enter to end the process..." << std::endl; - std::cin.ignore(); return -3; } diff --git a/docs/CHANGELOG.rst b/docs/CHANGELOG.rst index 2f8a5d2fa..d711c7ecb 100644 --- a/docs/CHANGELOG.rst +++ b/docs/CHANGELOG.rst @@ -10,6 +10,13 @@ The format is based on `Keep a Changelog (http://keepachangelog.com/en/1.0.0/) < [4.0.49] - UNRELEASED --------------------- + +Changed +~~~~~~~ + +- SystemController utility: Listen for Ctrl-C (SigInt) to end simulation. + Output messages better report about the system state. + Added ~~~~~ From a9905fdce291456939ce86723052d099c63c8917 Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Wed, 3 Apr 2024 14:51:54 +0200 Subject: [PATCH 04/15] SILKIT-1477 SystemController Utility: Use common SignalHandler --- SilKit/source/CMakeLists.txt | 1 + SilKit/source/core/vasio/VAsioConnection.cpp | 8 +- .../orchestration/LifecycleService.cpp | 8 +- SilKit/source/util/CMakeLists.txt | 12 +++ .../source/util}/SignalHandler.cpp | 74 ++++++++++++++----- .../source/util}/SignalHandler.hpp | 4 +- Utilities/SilKitRegistry/CMakeLists.txt | 4 +- Utilities/SilKitRegistry/Registry.cpp | 2 +- .../SilKitSystemController/CMakeLists.txt | 2 + .../SystemController.cpp | 53 +++++++------ 10 files changed, 116 insertions(+), 52 deletions(-) rename {Utilities/SilKitRegistry => SilKit/source/util}/SignalHandler.cpp (70%) mode change 100755 => 100644 rename {Utilities/SilKitRegistry => SilKit/source/util}/SignalHandler.hpp (97%) mode change 100755 => 100644 diff --git a/SilKit/source/CMakeLists.txt b/SilKit/source/CMakeLists.txt index 5688eecb0..800899155 100644 --- a/SilKit/source/CMakeLists.txt +++ b/SilKit/source/CMakeLists.txt @@ -186,6 +186,7 @@ list(APPEND SilKitImplObjectLibraries O_SilKit_Util_FileHelpers O_SilKit_Util_Filesystem O_SilKit_Util_SetThreadName + O_SilKit_Util_SignalHandler O_SilKit_Util_Uuid O_SilKit_Util_Uri O_SilKit_Util_LabelMatching diff --git a/SilKit/source/core/vasio/VAsioConnection.cpp b/SilKit/source/core/vasio/VAsioConnection.cpp index a19f48838..47807676a 100755 --- a/SilKit/source/core/vasio/VAsioConnection.cpp +++ b/SilKit/source/core/vasio/VAsioConnection.cpp @@ -668,6 +668,12 @@ void VAsioConnection::ReceiveParticipantAnnouncement(IVAsioPeer* from, Serialize { SILKIT_TRACE_METHOD_(_logger, "()"); + // ignore new participants after shutdown + if (_isShuttingDown) + { + return; + } + const auto remoteHeader = buffer.GetRegistryMessageHeader(); // check if we support the remote peer's protocol version or signal a handshake failure @@ -1350,7 +1356,7 @@ void VAsioConnection::RemovePeerFromConnection(IVAsioPeer* peer) void VAsioConnection::NotifyShutdown() { - _isShuttingDown = true; + //_isShuttingDown = true; } void VAsioConnection::OnSocketData(IVAsioPeer* from, SerializedMessage&& buffer) diff --git a/SilKit/source/services/orchestration/LifecycleService.cpp b/SilKit/source/services/orchestration/LifecycleService.cpp index ed7d20a4f..537ae48f7 100755 --- a/SilKit/source/services/orchestration/LifecycleService.cpp +++ b/SilKit/source/services/orchestration/LifecycleService.cpp @@ -524,13 +524,13 @@ void LifecycleService::NewSystemState(SystemState systemState) _lifecycleManager.ReadyToRun(ss.str()); break; case SystemState::Running: - _logger->Info("Simulation running"); + _logger->Info("Simulation is now running"); break; case SystemState::Paused: - _logger->Info("Simulation paused"); + _logger->Info("Simulation is paused"); break; case SystemState::Stopping: - _logger->Info("Simulation stopping"); + _logger->Info("Simulation is stopping"); // Only allow external stop signal if we are actually running or paused if (_lifecycleManager.GetCurrentState() == _lifecycleManager.GetRunningState() || _lifecycleManager.GetCurrentState() == _lifecycleManager.GetPausedState()) @@ -543,7 +543,7 @@ void LifecycleService::NewSystemState(SystemState systemState) case SystemState::ShuttingDown: break; case SystemState::Shutdown: - _logger->Info("Simulation has shutdown"); + _logger->Info("Simulation is shut down"); break; case SystemState::Aborting: break; diff --git a/SilKit/source/util/CMakeLists.txt b/SilKit/source/util/CMakeLists.txt index fc388a68b..fae5edf67 100644 --- a/SilKit/source/util/CMakeLists.txt +++ b/SilKit/source/util/CMakeLists.txt @@ -66,6 +66,18 @@ target_include_directories(O_SilKit_Util_SetThreadName INTERFACE ${CMAKE_CURRENT target_link_libraries(O_SilKit_Util_SetThreadName PUBLIC I_SilKit_Util_SetThreadName) +add_library(I_SilKit_Util_SignalHandler INTERFACE) +target_include_directories(I_SilKit_Util_SignalHandler INTERFACE ${CMAKE_CURRENT_LIST_DIR}) +target_link_libraries(I_SilKit_Util_SignalHandler INTERFACE SilKitInterface) + +add_library(O_SilKit_Util_SignalHandler OBJECT + SignalHandler.hpp + SignalHandler.cpp +) +target_include_directories(O_SilKit_Util_SignalHandler INTERFACE ${CMAKE_CURRENT_LIST_DIR}) +target_link_libraries(O_SilKit_Util_SignalHandler PUBLIC I_SilKit_Util_SignalHandler) + + add_library(I_SilKit_Util_Uuid INTERFACE) target_include_directories(I_SilKit_Util_Uuid INTERFACE ${CMAKE_CURRENT_LIST_DIR}) diff --git a/Utilities/SilKitRegistry/SignalHandler.cpp b/SilKit/source/util/SignalHandler.cpp old mode 100755 new mode 100644 similarity index 70% rename from Utilities/SilKitRegistry/SignalHandler.cpp rename to SilKit/source/util/SignalHandler.cpp index 7ba90c2ff..7a9435342 --- a/Utilities/SilKitRegistry/SignalHandler.cpp +++ b/SilKit/source/util/SignalHandler.cpp @@ -38,7 +38,7 @@ static std::unique_ptr gSignalMonitor; #include namespace { -using namespace SilKit::registry; +using namespace SilKit::Util; //forward BOOL WINAPI systemHandler(DWORD ctrlType); @@ -52,11 +52,17 @@ class SignalMonitor auto ok = CreatePipe(&_readEnd, &_writeEnd, nullptr, 0); if (!ok) - throw std::runtime_error("CreatePipe failed. Cannot create Signal Handler!"); + { + throw std::runtime_error("SignalMonitor: Failed to create pipe for signal handler."); + } DWORD nowait = PIPE_NOWAIT; ok = SetNamedPipeHandleState(_writeEnd, &nowait, nullptr, nullptr); if (!ok) - throw std::runtime_error("Set pipe read end to nonblocking failed. Cannot create Signal Handler!"); + { + throw std::runtime_error( + "SignalMonitor: Failed to create signal handler, cannot set read end of pipe to non-blocking."); + } + SetConsoleCtrlHandler(systemHandler, true); _worker = std::thread{std::bind(&SignalMonitor::workerMain, this)}; } @@ -70,7 +76,7 @@ class SignalMonitor } void Notify(int signalNumber) { - // no allocs, no error handling + // No allocs, no error handling _signalNumber = signalNumber; uint8_t buf{}; auto ok = WriteFile(_writeEnd, &buf, sizeof(buf), nullptr, nullptr); @@ -81,10 +87,12 @@ class SignalMonitor void workerMain() { std::vector buf(1); - //blocking read until Notify() was called + // Blocking read until Notify() was called auto ok = ReadFile(_readEnd, buf.data(), static_cast(buf.size()), nullptr, nullptr); if (!ok) - throw std::runtime_error("SignalMonitor::workerMain: cannot read from pipe."); + { + throw std::runtime_error("SignalMonitor::workerMain: Failed to read from pipe."); + } if (_handler) { @@ -119,7 +127,7 @@ BOOL WINAPI systemHandler(DWORD ctrlType) namespace { -using namespace SilKit::registry; +using namespace SilKit::Util; //forward void systemHandler(int sigNum); @@ -138,20 +146,27 @@ class SignalMonitor auto ok = ::pipe(_pipe); if (ok == -1) - throw std::runtime_error("SignalMonitor: pipe() failed! " + ErrorMessage()); + { + throw std::runtime_error("SignalMonitor: Failed to create pipe for signal handler, " + ErrorMessage()); + } ok = fcntl(_pipe[1], F_SETFL, O_NONBLOCK); if (ok == -1) - throw std::runtime_error("SignalMonitor: cannot set write end of pipe to non blocking: " + ErrorMessage()); + { + throw std::runtime_error( + "SignalMonitor: Failed to create signal handler, cannot set read end of pipe to non-blocking: " + + ErrorMessage()); + } - signal(SIGINT, &systemHandler); - signal(SIGTERM, &systemHandler); + setSignalAction(SIGINT, &systemHandler); + setSignalAction(SIGTERM, &systemHandler); _worker = std::thread{std::bind(&SignalMonitor::workerMain, this)}; } ~SignalMonitor() { - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); + // Restore default actio0ns + setSignalAction(SIGINT, SIG_DFL); + setSignalAction(SIGTERM, SIG_DFL); Notify(-1); _worker.join(); ::close(_pipe[0]); @@ -160,7 +175,7 @@ class SignalMonitor void Notify(int signalNumber) { - //in signal handler context: no allocs, no error handling + // In signal handler context: no allocs, no error handling _signalNumber = signalNumber; uint8_t buf{}; auto ok = ::write(_pipe[1], &buf, sizeof(buf)); @@ -168,13 +183,14 @@ class SignalMonitor } private: + void workerMain() { std::vector buf(1); - //blocking read until Notify() was called + // Blocking read until Notify() was called auto ok = ::read(_pipe[0], buf.data(), buf.size()); if (ok == -1) - throw std::runtime_error("SignalMonitor::workerMain: cannot read from pipe: " + ErrorMessage()); + throw std::runtime_error("SignalMonitor::workerMain: Failed to read from pipe: " + ErrorMessage()); if (_handler) { @@ -188,7 +204,27 @@ class SignalMonitor int _signalNumber{-1}; }; -void systemHandler(int sigNum) +static inline void setSignalAction(int sigNum, const struct sigaction *action) +{ + // Check current signal handler action to see if it's set to SIGNAL IGNORE + struct sigaction oldAction; + sigaction(sigNum, NULL, &oldAction); + if (oldAction.sa_handler == SIG_IGN) + { + // A non-job-control shell wants us to ignore this kind of signal + + } + // Set new signal handler action to what we want + struct sigaction newAction; + newAction.sa_handler = action; + auto ret = sigaction(sigNum, newAction, NULL); + if (ret == -1) + { + throw std::runtime_error("SignalMonitor: Failed to set handler for signal " + sigNum + ": " + ErrorMessage()); + } +} + +void systemHandler(const int sigNum) { if (gSignalMonitor) { @@ -200,12 +236,12 @@ void systemHandler(int sigNum) #endif namespace SilKit { -namespace registry { +namespace Util { void RegisterSignalHandler(SignalHandler handler) { gSignalMonitor.reset(new SignalMonitor(std::move(handler))); } -} // namespace registry +} // namespace Util } // namespace SilKit diff --git a/Utilities/SilKitRegistry/SignalHandler.hpp b/SilKit/source/util/SignalHandler.hpp old mode 100755 new mode 100644 similarity index 97% rename from Utilities/SilKitRegistry/SignalHandler.hpp rename to SilKit/source/util/SignalHandler.hpp index 688af7b00..06f561182 --- a/Utilities/SilKitRegistry/SignalHandler.hpp +++ b/SilKit/source/util/SignalHandler.hpp @@ -21,7 +21,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include namespace SilKit { -namespace registry { +namespace Util { //! \brief RegisterSignalHandler can be used to portably register a single signal handler. // It only relies on async-signal-safe C functions internally, but @@ -30,5 +30,5 @@ namespace registry { using SignalHandler = std::function; void RegisterSignalHandler(SignalHandler handler); -} // namespace registry +} // namespace Util } // namespace SilKit diff --git a/Utilities/SilKitRegistry/CMakeLists.txt b/Utilities/SilKitRegistry/CMakeLists.txt index aea60b432..7023bde47 100644 --- a/Utilities/SilKitRegistry/CMakeLists.txt +++ b/Utilities/SilKitRegistry/CMakeLists.txt @@ -34,8 +34,6 @@ endif (MSVC) add_subdirectory(config) add_executable(sil-kit-registry - SignalHandler.hpp - SignalHandler.cpp Registry.cpp WindowsServiceMain.hpp @@ -62,6 +60,8 @@ target_link_libraries(sil-kit-registry O_SilKit_Dashboard O_SilKitRegistry_Config + + O_SilKit_Util_SignalHandler ) # Set versioning infos on exe diff --git a/Utilities/SilKitRegistry/Registry.cpp b/Utilities/SilKitRegistry/Registry.cpp index d98d9d90b..21b997c23 100755 --- a/Utilities/SilKitRegistry/Registry.cpp +++ b/Utilities/SilKitRegistry/Registry.cpp @@ -513,7 +513,7 @@ int main(int argc, char** argv) if (useSignalHandler) { - using namespace SilKit::registry; + using namespace SilKit::Util; auto signalValue = signalPromise.get_future(); RegisterSignalHandler([](auto sigNum) { diff --git a/Utilities/SilKitSystemController/CMakeLists.txt b/Utilities/SilKitSystemController/CMakeLists.txt index cd9779e0d..3fe96ef0e 100644 --- a/Utilities/SilKitSystemController/CMakeLists.txt +++ b/Utilities/SilKitSystemController/CMakeLists.txt @@ -40,6 +40,8 @@ set_target_properties(sil-kit-system-controller PROPERTIES target_link_libraries(sil-kit-system-controller SilKit I_SilKit_Util + + O_SilKit_Util_SignalHandler ) # Set versioning infos on exe diff --git a/Utilities/SilKitSystemController/SystemController.cpp b/Utilities/SilKitSystemController/SystemController.cpp index 19647f7e1..b7c29ae89 100644 --- a/Utilities/SilKitSystemController/SystemController.cpp +++ b/Utilities/SilKitSystemController/SystemController.cpp @@ -38,6 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "silkit/experimental/participant/ParticipantExtensions.hpp" #include "CommandlineParser.hpp" +#include "SignalHandler.hpp" using namespace SilKit; using namespace SilKit::Services::Orchestration; @@ -147,7 +148,8 @@ class SilKitController _lifecycleService = participant->CreateLifecycleService({SilKit::Services::Orchestration::OperationMode::Coordinated}); - _finalStatePromise = _lifecycleService->StartLifecycle(); + auto finalStatePromise = _lifecycleService->StartLifecycle(); + _finalStatePromise = finalStatePromise.share(); } void StopOrAbort() @@ -180,6 +182,30 @@ class SilKitController } } + void RegisterSignalHandler() + { + SilKit::Util::RegisterSignalHandler([&](auto sigNum) { + StopOrAbort(); + WaitForFinalStateWithRetries(); + }); + } + + void WaitForExternalShutdown() + { + ParticipantState state = _finalStatePromise.get(); + if (state == ParticipantState::Shutdown) + { + //LogInfo("Simulation is shut down"); + } + else + { + std::ostringstream ss; + ss << "Warning: Exited with an unexpected participant state: " << state; + LogWarn(ss.str()); + } + } + +private: void WaitForFinalStateWithRetries() { const int numRetries = 3; @@ -213,6 +239,7 @@ class SilKitController if (_aborted) { LogWarn("Simulation did not shut down via abort signal. Terminating..."); + _lifecycleService->Stop("Enforced stop after no reaction to abort signal"); return; } else @@ -224,22 +251,6 @@ class SilKitController } } - void WaitForExternalShutdown() - { - ParticipantState state = _finalStatePromise.get(); - if (state == ParticipantState::Shutdown) - { - LogInfo("Simulation was shut down externally"); - } - else - { - std::ostringstream ss; - ss << "Warning: Exited with an unexpected participant state: " << state; - LogWarn(ss.str()); - } - } - -private: void LogInfo(const std::string& message) { _logger->Info(message); @@ -261,7 +272,7 @@ class SilKitController ISystemMonitor* _monitor; ILifecycleService* _lifecycleService; ILogger* _logger; - std::future _finalStatePromise; + std::shared_future _finalStatePromise; }; auto ToLowerCase(std::string s) -> std::string @@ -432,11 +443,7 @@ int main(int argc, char** argv) SilKitController controller(participant.get(), configuration, expectedParticipantNames); std::cout << "Press Ctrl-C to end the simulation..." << std::endl; - ConfigureSignalInterruptHandler([&]() { - controller.StopOrAbort(); - controller.WaitForFinalStateWithRetries(); - }); - + controller.RegisterSignalHandler(); controller.WaitForExternalShutdown(); } catch (const std::exception& error) From edbe5b7011e299978993feb9b10eb373c43ae95e Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Mon, 15 Apr 2024 14:21:31 +0200 Subject: [PATCH 05/15] SILKIT-1477 SystemController Utility: Revert experimental changes to VAsioConnection.cpp --- SilKit/source/core/vasio/VAsioConnection.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/SilKit/source/core/vasio/VAsioConnection.cpp b/SilKit/source/core/vasio/VAsioConnection.cpp index 47807676a..a19f48838 100755 --- a/SilKit/source/core/vasio/VAsioConnection.cpp +++ b/SilKit/source/core/vasio/VAsioConnection.cpp @@ -668,12 +668,6 @@ void VAsioConnection::ReceiveParticipantAnnouncement(IVAsioPeer* from, Serialize { SILKIT_TRACE_METHOD_(_logger, "()"); - // ignore new participants after shutdown - if (_isShuttingDown) - { - return; - } - const auto remoteHeader = buffer.GetRegistryMessageHeader(); // check if we support the remote peer's protocol version or signal a handshake failure @@ -1356,7 +1350,7 @@ void VAsioConnection::RemovePeerFromConnection(IVAsioPeer* peer) void VAsioConnection::NotifyShutdown() { - //_isShuttingDown = true; + _isShuttingDown = true; } void VAsioConnection::OnSocketData(IVAsioPeer* from, SerializedMessage&& buffer) From 3684914a0ea124c841a7f02696587955f6a7e86e Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Fri, 19 Apr 2024 09:27:46 +0200 Subject: [PATCH 06/15] SILKIT-1477 SystemController Utility: Add --non-interactive mode back --- Utilities/SilKitRegistry/Registry.cpp | 3 +- .../SystemController.cpp | 110 +++++++++++------- docs/usage/utilities.rst | 1 - 3 files changed, 69 insertions(+), 45 deletions(-) diff --git a/Utilities/SilKitRegistry/Registry.cpp b/Utilities/SilKitRegistry/Registry.cpp index 21b997c23..16a2e420e 100755 --- a/Utilities/SilKitRegistry/Registry.cpp +++ b/Utilities/SilKitRegistry/Registry.cpp @@ -523,8 +523,7 @@ int main(int argc, char** argv) signalValue.wait(); - std::cout << "Signal " << signalValue.get() << " received!" << std::endl; - std::cout << "Exiting..." << std::endl; + std::cout << "Signal " << signalValue.get() << " received, exiting..." << std::endl; } else { diff --git a/Utilities/SilKitSystemController/SystemController.cpp b/Utilities/SilKitSystemController/SystemController.cpp index b7c29ae89..462bf70bf 100644 --- a/Utilities/SilKitSystemController/SystemController.cpp +++ b/Utilities/SilKitSystemController/SystemController.cpp @@ -137,7 +137,6 @@ class SilKitController if (!_isStopRequested) { LogInfo("An external event causes the simulation to stop"); - fclose(stdin); } } else if (systemState == SystemState::Error) @@ -152,10 +151,49 @@ class SilKitController _finalStatePromise = finalStatePromise.share(); } + void RegisterSignalHandler() + { + SilKit::Util::RegisterSignalHandler([&](auto signalValue) { + { + std::ostringstream ss; + ss << "Signal " << signalValue << " received, attempting to stop simulation..."; + LogInfo(ss.str()); + } + StopOrAbort(); + WaitForFinalStateWithRetries(); + }); + } + + void WaitForFinalState() + { + ParticipantState state = _finalStatePromise.get(); + if (state != ParticipantState::Shutdown) + { + std::ostringstream ss; + ss << "Simulation exited with an unexpected participant state: " << state; + LogWarn(ss.str()); + } + else + { + if (_aborted) + { + LogWarn("Simulation was shut down by user request via abort signal"); + } + else if (_externalShutdown) + { + LogInfo("Simulation was shut down externally"); + } + else + { + LogInfo("Simulation was shut down by user request"); + } + } + } + +private: void StopOrAbort() { _isStopRequested = true; - LogInfo("User requested to stop"); if (_monitor->SystemState() == SystemState::Running || _monitor->SystemState() == SystemState::Paused) { LogInfo("System controller stops the simulation..."); @@ -182,30 +220,6 @@ class SilKitController } } - void RegisterSignalHandler() - { - SilKit::Util::RegisterSignalHandler([&](auto sigNum) { - StopOrAbort(); - WaitForFinalStateWithRetries(); - }); - } - - void WaitForExternalShutdown() - { - ParticipantState state = _finalStatePromise.get(); - if (state == ParticipantState::Shutdown) - { - //LogInfo("Simulation is shut down"); - } - else - { - std::ostringstream ss; - ss << "Warning: Exited with an unexpected participant state: " << state; - LogWarn(ss.str()); - } - } - -private: void WaitForFinalStateWithRetries() { const int numRetries = 3; @@ -214,18 +228,6 @@ class SilKitController auto status = _finalStatePromise.wait_for(5s); if (status == std::future_status::ready) { - if (_aborted) - { - LogWarn("Simulation was shut down by user request via abort signal"); - } - else if (_externalShutdown) - { - LogInfo("Simulation was shut down externally"); - } - else - { - LogInfo("Simulation was shut down by user request"); - } return; } else @@ -239,8 +241,7 @@ class SilKitController if (_aborted) { LogWarn("Simulation did not shut down via abort signal. Terminating..."); - _lifecycleService->Stop("Enforced stop after no reaction to abort signal"); - return; + _lifecycleService->ReportError("Simulation did not shut down via abort signal"); // TODO: Modify API to set the _finalStatePromise for Error state, not currently done. } else { @@ -261,6 +262,11 @@ class SilKitController _logger->Warn(message); } + void LogDebug(const std::string& message) + { + _logger->Debug(message); + } + private: std::shared_ptr _config; std::vector _expectedParticipantNames; @@ -303,6 +309,9 @@ int main(int argc, char** argv) CommandlineParser commandlineParser; commandlineParser.Add("version", "v", "[--version]", "-v, --version: Get version info."); commandlineParser.Add("help", "h", "[--help]", "-h, --help: Get this help."); + commandlineParser.Add( + "non-interactive", "ni", "[--non-interactive]", + "--non-interactive: Run without awaiting any user interactions at any time."); commandlineParser.Add( "connect-uri", "u", "silkit://localhost:8500", "[--connect-uri ]", "-u, --connect-uri : The registry URI to connect to. Defaults to 'silkit://localhost:8500'."); @@ -394,6 +403,9 @@ int main(int argc, char** argv) return -1; } + const bool nonInteractiveMode = + (commandlineParser.Get("non-interactive").Value()) ? true : false; + std::shared_ptr configuration; try { @@ -442,13 +454,27 @@ int main(int argc, char** argv) expectedParticipantNames.push_back(participantName); SilKitController controller(participant.get(), configuration, expectedParticipantNames); - std::cout << "Press Ctrl-C to end the simulation..." << std::endl; + if (!nonInteractiveMode) + { + std::cout << "Press Ctrl-C to end the simulation..." << std::endl; + } controller.RegisterSignalHandler(); - controller.WaitForExternalShutdown(); + controller.WaitForFinalState(); + + if (!nonInteractiveMode) + { + std::cout << "Press enter to end the process..." << std::endl; + std::cin.ignore(); + } } catch (const std::exception& error) { std::cerr << "Something went wrong: " << error.what() << std::endl; + if (!nonInteractiveMode) + { + std::cout << "Press enter to end the process..." << std::endl; + std::cin.ignore(); + } return -3; } diff --git a/docs/usage/utilities.rst b/docs/usage/utilities.rst index 84725ec3b..f8dcec562 100644 --- a/docs/usage/utilities.rst +++ b/docs/usage/utilities.rst @@ -82,7 +82,6 @@ sil-kit-system-controller -n, --name The participant name used to take part in the simulation. Defaults to ``SystemController``. -l, --log Log to stdout with level ``trace``, ``debug``, ``warn``, ``info``, ``error``, ``critical`` or ``off``. Defaults to ``info``. Cannot be used together with ``--configuration``. -c, --configuration Path and filename of the participant configuration YAML file. Cannot be used together with ``--log``. - -ni, --non-interactive Run without awaiting any user interactions at any time. | **, ...** | Names of participants to wait for before starting simulation. From b52f8d3dd98e154c6116b7a6bbd477a36a0208bf Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Mon, 22 Apr 2024 20:12:23 +0200 Subject: [PATCH 07/15] SILKIT-1477 Lifecycle state transition from Aborting to Shutdown is valid --- SilKit/source/services/orchestration/SystemStateTracker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SilKit/source/services/orchestration/SystemStateTracker.cpp b/SilKit/source/services/orchestration/SystemStateTracker.cpp index 987933725..eee43745b 100644 --- a/SilKit/source/services/orchestration/SystemStateTracker.cpp +++ b/SilKit/source/services/orchestration/SystemStateTracker.cpp @@ -58,7 +58,7 @@ auto ValidateParticipantStateUpdate(ParticipantState oldParticipantState, Partic return OldParticipantStateWas({ParticipantState::Error, ParticipantState::Stopped}); case ParticipantState::Shutdown: - return OldParticipantStateWas({ParticipantState::ShuttingDown}); + return OldParticipantStateWas({ParticipantState::ShuttingDown, ParticipantState::Aborting}); case ParticipantState::Aborting: case ParticipantState::Error: From 2a1c74a3124d029cc894a3a42ee25a46903f218a Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Mon, 22 Apr 2024 20:14:18 +0200 Subject: [PATCH 08/15] SILKIT-1477 SystemController Utility: Remove unused signal hander code --- .../SystemController.cpp | 56 ------------------- 1 file changed, 56 deletions(-) diff --git a/Utilities/SilKitSystemController/SystemController.cpp b/Utilities/SilKitSystemController/SystemController.cpp index 462bf70bf..680983b0d 100644 --- a/Utilities/SilKitSystemController/SystemController.cpp +++ b/Utilities/SilKitSystemController/SystemController.cpp @@ -55,62 +55,6 @@ std::ostream& operator<<(std::ostream& out, std::chrono::nanoseconds timestamp) namespace { -std::function signalInterruptHandler; - -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - -#include - -BOOL WINAPI HandleSignal(_In_ DWORD dwCtrlType) -{ - if (dwCtrlType == CTRL_C_EVENT) - { - signalInterruptHandler(); - } - return FALSE; -} - -void ConfigureSignalInterruptHandler(std::function handler) -{ - signalInterruptHandler = handler; - - if (SetConsoleCtrlHandler(HandleSignal, TRUE) == FALSE) - { - throw std::runtime_error("Failed to install OS signal handler"); - } -} - -#elif defined(linux) || defined(__linux) || defined(__linux__) || \ - defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) - -#include - -void HandleSignal(int signum) -{ - if (signum == SIGINT) - { - signalHandler(); - } -} - -void ConfigureSignalInterruptHandler(std::function handler) -{ - signalInterruptHandler = handler; - - struct sigaction action; - action.sa_handler = &HandleSignal; - sigemptyset(&action.sa_mask); - action.sa_flags = 0; - if (sigaction(SIGINT, &action, nullptr) != 0) - { - throw std::runtime_error("Failed to install OS signal handler"); - } -} - -#else -#error Unsupported operating system -#endif - class SilKitController { public: From ab9b372a37ee6fbfd908937fcd27d1fdc1b5bf92 Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Mon, 22 Apr 2024 20:14:46 +0200 Subject: [PATCH 09/15] SILKIT-1477 Fix clang build --- SilKit/source/util/SignalHandler.cpp | 9 +++++---- Utilities/SilKitSystemController/SystemController.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/SilKit/source/util/SignalHandler.cpp b/SilKit/source/util/SignalHandler.cpp index 7a9435342..76a0b4e29 100644 --- a/SilKit/source/util/SignalHandler.cpp +++ b/SilKit/source/util/SignalHandler.cpp @@ -130,9 +130,10 @@ namespace { using namespace SilKit::Util; //forward +static inline void setSignalAction(int sigNum, __sighandler_t action); void systemHandler(int sigNum); -auto ErrorMessage() + auto ErrorMessage() { return std::string{strerror(errno)}; } @@ -204,7 +205,7 @@ class SignalMonitor int _signalNumber{-1}; }; -static inline void setSignalAction(int sigNum, const struct sigaction *action) +static inline void setSignalAction(int sigNum, __sighandler_t action) { // Check current signal handler action to see if it's set to SIGNAL IGNORE struct sigaction oldAction; @@ -217,10 +218,10 @@ static inline void setSignalAction(int sigNum, const struct sigaction *action) // Set new signal handler action to what we want struct sigaction newAction; newAction.sa_handler = action; - auto ret = sigaction(sigNum, newAction, NULL); + auto ret = sigaction(sigNum, &newAction, NULL); if (ret == -1) { - throw std::runtime_error("SignalMonitor: Failed to set handler for signal " + sigNum + ": " + ErrorMessage()); + throw std::runtime_error("SignalMonitor: Failed to set handler for signal " + std::to_string(sigNum) + ": " + ErrorMessage()); } } diff --git a/Utilities/SilKitSystemController/SystemController.cpp b/Utilities/SilKitSystemController/SystemController.cpp index 680983b0d..6e7acd1ed 100644 --- a/Utilities/SilKitSystemController/SystemController.cpp +++ b/Utilities/SilKitSystemController/SystemController.cpp @@ -215,7 +215,7 @@ class SilKitController std::shared_ptr _config; std::vector _expectedParticipantNames; - std::atomic _isStopRequested = false; + std::atomic _isStopRequested{false}; bool _aborted = false; bool _externalShutdown = false; SilKit::Experimental::Services::Orchestration::ISystemController* _controller; From 03acf49975b3fe0708e71b1427a76d066fb05050 Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Mon, 22 Apr 2024 20:16:35 +0200 Subject: [PATCH 10/15] SILKIT-1477 Just warn if reply barrier is entered while still active --- SilKit/source/core/requests/procs/ParticipantReplies.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SilKit/source/core/requests/procs/ParticipantReplies.cpp b/SilKit/source/core/requests/procs/ParticipantReplies.cpp index eb9266891..42c3ce755 100644 --- a/SilKit/source/core/requests/procs/ParticipantReplies.cpp +++ b/SilKit/source/core/requests/procs/ParticipantReplies.cpp @@ -47,8 +47,9 @@ void ParticipantReplies::CallAfterAllParticipantsReplied(std::function c if (_barrierActive) { - Services::Logging::Debug(_participant->GetLogger(), "Only one barrier can be active at a time, ignoring."); - return; + Services::Logging::Debug(_participant->GetLogger(), + "Still waiting at a barrier for replies from participants, starting a new barrier " + "can lead to unexpected behavior."); } auto remoteReceivers = From c72bdd111a2bc95043668d6f9a711af19cb67964 Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Wed, 24 Apr 2024 16:17:45 +0200 Subject: [PATCH 11/15] SILKIT-1477 Shut down participant even in case of Error --- SilKit/source/services/orchestration/LifecycleStates.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SilKit/source/services/orchestration/LifecycleStates.cpp b/SilKit/source/services/orchestration/LifecycleStates.cpp index fd8447019..f1fd5b14f 100755 --- a/SilKit/source/services/orchestration/LifecycleStates.cpp +++ b/SilKit/source/services/orchestration/LifecycleStates.cpp @@ -708,7 +708,6 @@ void ShutdownState::ShutdownParticipant(std::string reason) if (success) { _lifecycleManager->NotifyShutdownInConnection(); - _lifecycleManager->GetService()->SetFinalStatePromise(); } else { @@ -716,7 +715,8 @@ void ShutdownState::ShutdownParticipant(std::string reason) "lifecycle failed to shut down correctly - original shutdown reason was '{}'.", std::move(reason)); } - }); + _lifecycleManager->GetService()->SetFinalStatePromise(); + }); } void ShutdownState::AbortSimulation(std::string /*reason*/) From ad8bb9a4504c741fa5fa3625e38a6e5eb34ee418 Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Thu, 25 Apr 2024 09:29:16 +0200 Subject: [PATCH 12/15] SILKIT-1477 SystemController Utility: Cleanup messages --- .../SystemController.cpp | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/Utilities/SilKitSystemController/SystemController.cpp b/Utilities/SilKitSystemController/SystemController.cpp index 6e7acd1ed..a48e47977 100644 --- a/Utilities/SilKitSystemController/SystemController.cpp +++ b/Utilities/SilKitSystemController/SystemController.cpp @@ -80,7 +80,7 @@ class SilKitController { if (!_isStopRequested) { - LogInfo("An external event causes the simulation to stop"); + LogInfo("Another participant causes the simulation to stop"); } } else if (systemState == SystemState::Error) @@ -114,23 +114,12 @@ class SilKitController if (state != ParticipantState::Shutdown) { std::ostringstream ss; - ss << "Simulation exited with an unexpected participant state: " << state; + ss << "Simulation ended with an unexpected participant state: " << state; LogWarn(ss.str()); } else { - if (_aborted) - { - LogWarn("Simulation was shut down by user request via abort signal"); - } - else if (_externalShutdown) - { - LogInfo("Simulation was shut down externally"); - } - else - { - LogInfo("Simulation was shut down by user request"); - } + LogInfo("Simulation ended, SystemController is shut down."); } } @@ -148,11 +137,7 @@ class SilKitController LogWarn("Simulation is already aborting..."); _aborted = true; } - else if (_monitor->SystemState() == SystemState::Shutdown) - { - _externalShutdown = true; - } - else + else if (_monitor->SystemState() != SystemState::Shutdown) { { std::ostringstream ss; @@ -185,7 +170,7 @@ class SilKitController if (_aborted) { LogWarn("Simulation did not shut down via abort signal. Terminating..."); - _lifecycleService->ReportError("Simulation did not shut down via abort signal"); // TODO: Modify API to set the _finalStatePromise for Error state, not currently done. + _lifecycleService->ReportError("Simulation did not shut down via abort signal"); } else { @@ -217,7 +202,6 @@ class SilKitController std::atomic _isStopRequested{false}; bool _aborted = false; - bool _externalShutdown = false; SilKit::Experimental::Services::Orchestration::ISystemController* _controller; ISystemMonitor* _monitor; ILifecycleService* _lifecycleService; From 48da4eebd1c4f7c61443ef2a2a99eddda3cc018d Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Thu, 25 Apr 2024 09:52:18 +0200 Subject: [PATCH 13/15] SILKIT-1477 Update CHANGELOG.rst --- docs/CHANGELOG.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.rst b/docs/CHANGELOG.rst index d711c7ecb..086aa35db 100644 --- a/docs/CHANGELOG.rst +++ b/docs/CHANGELOG.rst @@ -14,9 +14,17 @@ The format is based on `Keep a Changelog (http://keepachangelog.com/en/1.0.0/) < Changed ~~~~~~~ -- SystemController utility: Listen for Ctrl-C (SigInt) to end simulation. +- SystemController utility: + Listens for OS signals to end simulation: Press ``[Ctrl]-[C]`` (SigInt) instead of ``[Enter]`` to end simulation. Output messages better report about the system state. +Fixed +~~~~~ + +- SystemController utility: + Error state ends the simulation. +- Valid state transition from ``Aborting`` to ``Shutdown`` no longer emits a warning message. + Added ~~~~~ From 3bde84a5309924675e71b937135b5ec46f918988 Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Thu, 25 Apr 2024 09:54:26 +0200 Subject: [PATCH 14/15] SILKIT-1477 SystemController Utility: Revert documentation changes --- docs/usage/utilities.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/usage/utilities.rst b/docs/usage/utilities.rst index f8dcec562..84725ec3b 100644 --- a/docs/usage/utilities.rst +++ b/docs/usage/utilities.rst @@ -82,6 +82,7 @@ sil-kit-system-controller -n, --name The participant name used to take part in the simulation. Defaults to ``SystemController``. -l, --log Log to stdout with level ``trace``, ``debug``, ``warn``, ``info``, ``error``, ``critical`` or ``off``. Defaults to ``info``. Cannot be used together with ``--configuration``. -c, --configuration Path and filename of the participant configuration YAML file. Cannot be used together with ``--log``. + -ni, --non-interactive Run without awaiting any user interactions at any time. | **, ...** | Names of participants to wait for before starting simulation. From 9bc59c4f20c7ef4e493593c9e95b7f429bee5cc4 Mon Sep 17 00:00:00 2001 From: "Rentschler, Andreas" Date: Fri, 26 Apr 2024 20:08:38 +0200 Subject: [PATCH 15/15] SILKIT-1477 SystemController Utility: Changes based on code reviews * Reverted change which made error state a final state, so that the system can still be debugged * Reverted change that made previous call-replied action be ignored, so that new call-replied action will be ignored, as previously. Issue must be handled correctly, e.g. by supporting multiple barriers. * Fixed several issues in SignalHandler.cpp --- SilKit/source/core/requests/procs/ParticipantReplies.cpp | 5 +++-- SilKit/source/services/orchestration/LifecycleStates.cpp | 2 +- SilKit/source/util/SignalHandler.cpp | 9 +++++---- docs/CHANGELOG.rst | 4 +--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/SilKit/source/core/requests/procs/ParticipantReplies.cpp b/SilKit/source/core/requests/procs/ParticipantReplies.cpp index 42c3ce755..87f4efb26 100644 --- a/SilKit/source/core/requests/procs/ParticipantReplies.cpp +++ b/SilKit/source/core/requests/procs/ParticipantReplies.cpp @@ -48,8 +48,9 @@ void ParticipantReplies::CallAfterAllParticipantsReplied(std::function c if (_barrierActive) { Services::Logging::Debug(_participant->GetLogger(), - "Still waiting at a barrier for replies from participants, starting a new barrier " - "can lead to unexpected behavior."); + "Still waiting for replies from participants on a previous call, action when new " + "call is replied will not be executed. This might lead to unexpected behavior."); + return; } auto remoteReceivers = diff --git a/SilKit/source/services/orchestration/LifecycleStates.cpp b/SilKit/source/services/orchestration/LifecycleStates.cpp index f1fd5b14f..cd2ab2173 100755 --- a/SilKit/source/services/orchestration/LifecycleStates.cpp +++ b/SilKit/source/services/orchestration/LifecycleStates.cpp @@ -708,6 +708,7 @@ void ShutdownState::ShutdownParticipant(std::string reason) if (success) { _lifecycleManager->NotifyShutdownInConnection(); + _lifecycleManager->GetService()->SetFinalStatePromise(); } else { @@ -715,7 +716,6 @@ void ShutdownState::ShutdownParticipant(std::string reason) "lifecycle failed to shut down correctly - original shutdown reason was '{}'.", std::move(reason)); } - _lifecycleManager->GetService()->SetFinalStatePromise(); }); } diff --git a/SilKit/source/util/SignalHandler.cpp b/SilKit/source/util/SignalHandler.cpp index 76a0b4e29..077c22635 100644 --- a/SilKit/source/util/SignalHandler.cpp +++ b/SilKit/source/util/SignalHandler.cpp @@ -191,8 +191,9 @@ class SignalMonitor // Blocking read until Notify() was called auto ok = ::read(_pipe[0], buf.data(), buf.size()); if (ok == -1) + { throw std::runtime_error("SignalMonitor::workerMain: Failed to read from pipe: " + ErrorMessage()); - + } if (_handler) { _handler(_signalNumber); @@ -208,15 +209,15 @@ class SignalMonitor static inline void setSignalAction(int sigNum, __sighandler_t action) { // Check current signal handler action to see if it's set to SIGNAL IGNORE - struct sigaction oldAction; + struct sigaction oldAction{}; sigaction(sigNum, NULL, &oldAction); if (oldAction.sa_handler == SIG_IGN) { // A non-job-control shell wants us to ignore this kind of signal - + return; } // Set new signal handler action to what we want - struct sigaction newAction; + struct sigaction newAction{}; newAction.sa_handler = action; auto ret = sigaction(sigNum, &newAction, NULL); if (ret == -1) diff --git a/docs/CHANGELOG.rst b/docs/CHANGELOG.rst index 086aa35db..2ebf88215 100644 --- a/docs/CHANGELOG.rst +++ b/docs/CHANGELOG.rst @@ -16,13 +16,11 @@ Changed - SystemController utility: Listens for OS signals to end simulation: Press ``[Ctrl]-[C]`` (SigInt) instead of ``[Enter]`` to end simulation. - Output messages better report about the system state. + Better reports about the current system state in case of Error. Fixed ~~~~~ -- SystemController utility: - Error state ends the simulation. - Valid state transition from ``Aborting`` to ``Shutdown`` no longer emits a warning message. Added