Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SILKIT-1477 SystemController Utility: Use SignalHandler, better report state #33

Merged
merged 15 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
46e6ed3
SILKIT-1477 SystemController Utility: Improve messages for certain sc…
AndreasRentschler Mar 22, 2024
f727e1b
SILKIT-1477 SystemController Utility: Improve messages for certain sc…
AndreasRentschler Mar 22, 2024
aa0b2c0
SILKIT-1477 SystemController Utility: Replace interactive mode with S…
AndreasRentschler Mar 27, 2024
a9905fd
SILKIT-1477 SystemController Utility: Use common SignalHandler
AndreasRentschler Apr 3, 2024
edbe5b7
SILKIT-1477 SystemController Utility: Revert experimental changes to …
AndreasRentschler Apr 15, 2024
3684914
SILKIT-1477 SystemController Utility: Add --non-interactive mode back
AndreasRentschler Apr 19, 2024
b52f8d3
SILKIT-1477 Lifecycle state transition from Aborting to Shutdown is v…
AndreasRentschler Apr 22, 2024
2a1c74a
SILKIT-1477 SystemController Utility: Remove unused signal hander code
AndreasRentschler Apr 22, 2024
ab9b372
SILKIT-1477 Fix clang build
AndreasRentschler Apr 22, 2024
03acf49
SILKIT-1477 Just warn if reply barrier is entered while still active
AndreasRentschler Apr 22, 2024
c72bdd1
SILKIT-1477 Shut down participant even in case of Error
AndreasRentschler Apr 24, 2024
ad8bb9a
SILKIT-1477 SystemController Utility: Cleanup messages
AndreasRentschler Apr 25, 2024
48da4ee
SILKIT-1477 Update CHANGELOG.rst
AndreasRentschler Apr 25, 2024
3bde84a
SILKIT-1477 SystemController Utility: Revert documentation changes
AndreasRentschler Apr 25, 2024
9bc59c4
SILKIT-1477 SystemController Utility: Changes based on code reviews
AndreasRentschler Apr 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions SilKit/source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion SilKit/source/core/requests/procs/ParticipantReplies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ void ParticipantReplies::CallAfterAllParticipantsReplied(std::function<void()> c

if (_barrierActive)
{
Services::Logging::Debug(_participant->GetLogger(), "Only one barrier can be active at a time, ignoring.");
Services::Logging::Debug(_participant->GetLogger(),
"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;
AndreasRentschler marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
8 changes: 4 additions & 4 deletions SilKit/source/services/orchestration/LifecycleService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion SilKit/source/services/orchestration/LifecycleStates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ void ShutdownState::ShutdownParticipant(std::string reason)
"lifecycle failed to shut down correctly - original shutdown reason was '{}'.",
std::move(reason));
}
});
});
}

void ShutdownState::AbortSimulation(std::string /*reason*/)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
12 changes: 12 additions & 0 deletions SilKit/source/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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})

Expand Down
80 changes: 59 additions & 21 deletions Utilities/SilKitRegistry/SignalHandler.cpp → SilKit/source/util/SignalHandler.cpp
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static std::unique_ptr<SignalMonitor> gSignalMonitor;
#include <windows.h>

namespace {
using namespace SilKit::registry;
using namespace SilKit::Util;

//forward
BOOL WINAPI systemHandler(DWORD ctrlType);
Expand All @@ -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)};
}
Expand All @@ -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);
Expand All @@ -81,10 +87,12 @@ class SignalMonitor
void workerMain()
{
std::vector<uint8_t> buf(1);
//blocking read until Notify() was called
// Blocking read until Notify() was called
auto ok = ReadFile(_readEnd, buf.data(), static_cast<DWORD>(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)
{
Expand Down Expand Up @@ -119,12 +127,13 @@ BOOL WINAPI systemHandler(DWORD ctrlType)

namespace {

using namespace SilKit::registry;
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)};
}
Expand All @@ -138,20 +147,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]);
Expand All @@ -160,22 +176,24 @@ 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));
(void)ok;
}

private:

void workerMain()
{
std::vector<uint8_t> 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)
{
_handler(_signalNumber);
Expand All @@ -188,7 +206,27 @@ class SignalMonitor
int _signalNumber{-1};
};

void systemHandler(int sigNum)
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{};
sigaction(sigNum, NULL, &oldAction);
if (oldAction.sa_handler == SIG_IGN)
{
// A non-job-control shell wants us to ignore this kind of signal
AndreasRentschler marked this conversation as resolved.
Show resolved Hide resolved
return;
}
// 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 " + std::to_string(sigNum) + ": " + ErrorMessage());
}
}

void systemHandler(const int sigNum)
{
if (gSignalMonitor)
{
Expand All @@ -200,12 +238,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
4 changes: 2 additions & 2 deletions Utilities/SilKitRegistry/SignalHandler.hpp → SilKit/source/util/SignalHandler.hpp
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <functional>

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
Expand All @@ -30,5 +30,5 @@ namespace registry {
using SignalHandler = std::function<void(int)>;
void RegisterSignalHandler(SignalHandler handler);

} // namespace registry
} // namespace Util
} // namespace SilKit
4 changes: 2 additions & 2 deletions Utilities/SilKitRegistry/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ endif (MSVC)
add_subdirectory(config)

add_executable(sil-kit-registry
SignalHandler.hpp
SignalHandler.cpp
Registry.cpp

WindowsServiceMain.hpp
Expand All @@ -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
Expand Down
5 changes: 2 additions & 3 deletions Utilities/SilKitRegistry/Registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
{
Expand Down
2 changes: 2 additions & 0 deletions Utilities/SilKitSystemController/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading