From ae3eb5c2199f8d948a3946c19d2cd2f48bb8d46e Mon Sep 17 00:00:00 2001 From: Alexey Sokolov Date: Sat, 23 Jan 2016 11:55:03 +0000 Subject: [PATCH] Revert "Revert "Fix delay between receiving signal in separate thread and handling it"" This reverts commit 615d936b6cf32350c289f291c5dc7f2734cfaf31. I forgot the condition before... --- src/main.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/znc.cpp | 4 ++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 78c1ed85..f6bf0a76 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -146,6 +146,12 @@ static void GenerateHelp(const char* appname) { class CSignalHandler { public: CSignalHandler(CZNC* pZNC) { + if (pipe(m_iPipe)) { + DEBUG("Ouch, can't open pipe for signal handler: " + << strerror(errno)); + exit(1); + } + pZNC->GetManager().MonitorFD(new CSignalHandlerMonitorFD(m_iPipe[0])); sigset_t signals; sigfillset(&signals); pthread_sigmask(SIG_SETMASK, &signals, nullptr); @@ -157,6 +163,23 @@ class CSignalHandler { } private: + class CSignalHandlerMonitorFD : public CSMonitorFD { + // This class just prevents the pipe buffer from filling by clearing it + public: + CSignalHandlerMonitorFD(int fd) { Add(fd, CSockManager::ECT_Read); } + + bool FDsThatTriggered( + const std::map& miiReadyFds) override { + for (const auto& it : miiReadyFds) { + if (it.second) { + int sig; + read(it.first, &sig, sizeof(sig)); + } + } + return true; + } + }; + void HandleSignals(CZNC* pZNC) { sigset_t signals; sigemptyset(&signals); @@ -176,6 +199,7 @@ class CSignalHandler { // Such cancel will be the only way to finish this thread. if (sigwait(&signals, &sig) == -1) continue; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr); + // TODO probably move switch() to CSignalHandlerMonitorFD? switch (sig) { case SIGHUP: pZNC->SetConfigState(CZNC::ECONFIG_NEED_REHASH); @@ -199,10 +223,23 @@ class CSignalHandler { default: break; } + // This write() must succeed because POSIX guarantees that writes of + // less than PIPE_BUF are atomic (and PIPE_BUF is at least 512). + size_t w = write(m_iPipe[1], &sig, sizeof(sig)); + if (w != sizeof(sig)) { + DEBUG( + "Something bad happened during write() to a pipe for " + "signal handler, wrote " + << w << " bytes: " << strerror(errno)); + exit(1); + } } } std::thread m_thread; + + // pipe for waking up the main thread + int m_iPipe[2]; }; static bool isRoot() { diff --git a/src/znc.cpp b/src/znc.cpp index d8264a7d..2790b690 100644 --- a/src/znc.cpp +++ b/src/znc.cpp @@ -243,8 +243,8 @@ void CZNC::Loop() { } // Csocket wants micro seconds - // 100 msec to 5 sec - m_Manager.DynamicSelectLoop(100 * 1000, 5 * 1000 * 1000); + // 100 msec to 5 min + m_Manager.DynamicSelectLoop(100 * 1000, 5 * 60 * 1000 * 1000); } }