mirror of https://github.com/aria2/aria2
Win: Use SetConsoleCtrlHandler for SIGINT/SIGTERM
parent
9e25335850
commit
79fcafc31f
|
@ -83,6 +83,7 @@ namespace global {
|
||||||
// 2 ... stop signal processed by DownloadEngine
|
// 2 ... stop signal processed by DownloadEngine
|
||||||
// 3 ... 2nd stop signal(force shutdown) detected
|
// 3 ... 2nd stop signal(force shutdown) detected
|
||||||
// 4 ... 2nd stop signal processed by DownloadEngine
|
// 4 ... 2nd stop signal processed by DownloadEngine
|
||||||
|
// 5 ... main loop exited
|
||||||
volatile sig_atomic_t globalHaltRequested = 0;
|
volatile sig_atomic_t globalHaltRequested = 0;
|
||||||
|
|
||||||
} // namespace global
|
} // namespace global
|
||||||
|
@ -141,6 +142,13 @@ void executeCommand(std::deque<std::unique_ptr<Command>>& commands,
|
||||||
|
|
||||||
int DownloadEngine::run(bool oneshot)
|
int DownloadEngine::run(bool oneshot)
|
||||||
{
|
{
|
||||||
|
class GHR {
|
||||||
|
public:
|
||||||
|
~GHR() {
|
||||||
|
global::globalHaltRequested = 5;
|
||||||
|
}
|
||||||
|
} ghr;
|
||||||
|
|
||||||
while(!commands_.empty() || !routineCommands_.empty()) {
|
while(!commands_.empty() || !routineCommands_.empty()) {
|
||||||
if(!commands_.empty()) {
|
if(!commands_.empty()) {
|
||||||
waitData();
|
waitData();
|
||||||
|
|
|
@ -86,21 +86,44 @@ extern volatile sig_atomic_t globalHaltRequested;
|
||||||
} // namespace global
|
} // namespace global
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void handler(int signal) {
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static const DWORD mainThread = GetCurrentThreadId();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void handler(int signal)
|
||||||
|
{
|
||||||
if(
|
if(
|
||||||
#ifdef SIGHUP
|
#ifdef SIGHUP
|
||||||
signal == SIGHUP ||
|
signal == SIGHUP ||
|
||||||
#endif // SIGHUP
|
#endif // SIGHUP
|
||||||
signal == SIGTERM) {
|
signal == SIGTERM) {
|
||||||
if(global::globalHaltRequested == 0 || global::globalHaltRequested == 2) {
|
if(global::globalHaltRequested <= 2) {
|
||||||
global::globalHaltRequested = 3;
|
global::globalHaltRequested = 3;
|
||||||
}
|
}
|
||||||
} else {
|
#ifdef _WIN32
|
||||||
if(global::globalHaltRequested == 0) {
|
if (::GetCurrentThreadId() != mainThread) {
|
||||||
|
// SIGTERM may arrive on another thread (via SetConsoleCtrlHandler), and
|
||||||
|
// the process will be forcefully terminated as soon as that thread is
|
||||||
|
// done. So better make sure it isn't done prematurely. ;)
|
||||||
|
while (global::globalHaltRequested != 5) {
|
||||||
|
::Sleep(100); // Yeah, semi-busy waiting for now.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIGINT
|
||||||
|
|
||||||
|
if (global::globalHaltRequested == 0) {
|
||||||
global::globalHaltRequested = 1;
|
global::globalHaltRequested = 1;
|
||||||
} else if(global::globalHaltRequested == 2) {
|
return;
|
||||||
global::globalHaltRequested = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (global::globalHaltRequested == 2) {
|
||||||
|
global::globalHaltRequested = 3;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
76
src/util.cc
76
src/util.cc
|
@ -84,6 +84,7 @@
|
||||||
#include "BufferedFile.h"
|
#include "BufferedFile.h"
|
||||||
#include "SocketCore.h"
|
#include "SocketCore.h"
|
||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
|
#include "Lock.h"
|
||||||
|
|
||||||
#ifdef ENABLE_MESSAGE_DIGEST
|
#ifdef ENABLE_MESSAGE_DIGEST
|
||||||
# include "MessageDigest.h"
|
# include "MessageDigest.h"
|
||||||
|
@ -1232,8 +1233,83 @@ bool isNumericHost(const std::string& name)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
namespace {
|
||||||
|
static Lock win_signal_lock;
|
||||||
|
|
||||||
|
static void(*win_int_handler)(int) = nullptr;
|
||||||
|
static void(*win_term_handler)(int) = nullptr;
|
||||||
|
|
||||||
|
static void win_ign_handler(int) {}
|
||||||
|
|
||||||
|
static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
|
||||||
|
{
|
||||||
|
void(*handler)(int) = nullptr;
|
||||||
|
switch (ctrlType) {
|
||||||
|
case CTRL_C_EVENT:
|
||||||
|
case CTRL_BREAK_EVENT:
|
||||||
|
{
|
||||||
|
// Handler will be called on a new/different thread.
|
||||||
|
LockGuard lg(win_signal_lock);
|
||||||
|
handler = win_int_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler) {
|
||||||
|
handler(SIGINT);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case CTRL_LOGOFF_EVENT:
|
||||||
|
case CTRL_CLOSE_EVENT:
|
||||||
|
case CTRL_SHUTDOWN_EVENT:
|
||||||
|
{
|
||||||
|
// Handler will be called on a new/different thread.
|
||||||
|
LockGuard lg(win_signal_lock);
|
||||||
|
handler = win_term_handler;;
|
||||||
|
}
|
||||||
|
if (handler) {
|
||||||
|
handler(SIGTERM);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void setGlobalSignalHandler(int sig, sigset_t* mask, void (*handler)(int),
|
void setGlobalSignalHandler(int sig, sigset_t* mask, void (*handler)(int),
|
||||||
int flags) {
|
int flags) {
|
||||||
|
#if _WIN32
|
||||||
|
if (sig == SIGINT || sig == SIGTERM) {
|
||||||
|
// Handler will be called on a new/different thread.
|
||||||
|
LockGuard lg(win_signal_lock);
|
||||||
|
|
||||||
|
if (handler == SIG_DFL) {
|
||||||
|
handler = nullptr;
|
||||||
|
}
|
||||||
|
else if (handler == SIG_IGN) {
|
||||||
|
handler = win_ign_handler;
|
||||||
|
}
|
||||||
|
// Not yet in use: add console handler.
|
||||||
|
if (handler && !win_int_handler && !win_term_handler) {
|
||||||
|
::SetConsoleCtrlHandler(HandlerRoutine, TRUE);
|
||||||
|
}
|
||||||
|
if (sig == SIGINT) {
|
||||||
|
win_int_handler = handler;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
win_term_handler = handler;
|
||||||
|
}
|
||||||
|
// No handlers set: remove.
|
||||||
|
if (!win_int_handler && !win_term_handler) {
|
||||||
|
::SetConsoleCtrlHandler(HandlerRoutine, FALSE);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SIGACTION
|
#ifdef HAVE_SIGACTION
|
||||||
struct sigaction sigact;
|
struct sigaction sigact;
|
||||||
sigact.sa_handler = handler;
|
sigact.sa_handler = handler;
|
||||||
|
|
Loading…
Reference in New Issue