init: Signal-safe instant shutdown

Replace the 200ms polling loop with a faster and more efficient waiting
operation.

This was tried a few times before, but given up every time because
solutions use a condition variable which is not safe for use in signals
as they need to be reentrant.

On UNIX-ish OSes, use a safe way: a pipe. When shutdown is requested
write a dummy byte to the pipe. Waiting for shutdown is a matter of a
blocking read from the pipe.

On Windows, there are no signals so using a condition variable is safe.
This commit is contained in:
Wladimir J. van der Laan
2020-12-08 21:49:06 +01:00
parent 16b31cc4c5
commit cd03513dc2
4 changed files with 112 additions and 14 deletions

View File

@@ -28,15 +28,6 @@
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
UrlDecodeFn* const URL_DECODE = urlDecode;
static void WaitForShutdown(NodeContext& node)
{
while (!ShutdownRequested())
{
UninterruptibleSleep(std::chrono::milliseconds{200});
}
Interrupt(node);
}
static bool AppInit(int argc, char* argv[])
{
NodeContext node;
@@ -147,12 +138,10 @@ static bool AppInit(int argc, char* argv[])
PrintExceptionContinue(nullptr, "AppInit()");
}
if (!fRet)
{
Interrupt(node);
} else {
WaitForShutdown(node);
if (fRet) {
WaitForShutdown();
}
Interrupt(node);
Shutdown(node);
return fRet;