From 5bafef3957bc32a2deb5a917c7773fcd92e8b953 Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Fri, 12 Apr 2013 12:24:34 +0200 Subject: engine: support additional signals in SuspendFlags It can be useful to use additional signals like SIGURG or SIGIO (typically not used elsewhere) for simple interprocess communication. SuspendFlags now supports that by letting the process catch more than just SIGINT and SIGTERM and recording which signals were received. activate() calls can happen when already active, for example when syncevo-dbus-helper instantiates SyncContext, which activates signal handling for the duration of the sync. This was not handled well before, leaking previously allocated FDs and not restoring signal handlers correctly. Because the process quit anyway soon, this did not matter in practice. Now the code explicitly checks for this and returns the existing Guard in all following activate() calls, without changing the signal handling. --- src/syncevo/SuspendFlags.cpp | 79 +++++++++++++++++++++++++++++--------------- src/syncevo/SuspendFlags.h | 42 +++++++++++++++++++---- 2 files changed, 88 insertions(+), 33 deletions(-) diff --git a/src/syncevo/SuspendFlags.cpp b/src/syncevo/SuspendFlags.cpp index b47a8524..0f46bc49 100644 --- a/src/syncevo/SuspendFlags.cpp +++ b/src/syncevo/SuspendFlags.cpp @@ -36,9 +36,11 @@ SE_BEGIN_CXX SuspendFlags::SuspendFlags() : m_level(Logger::INFO), m_state(NORMAL), + m_receivedSignals(0), m_lastSuspend(0), m_senderFD(-1), - m_receiverFD(-1) + m_receiverFD(-1), + m_activeSignals(0) { } @@ -148,10 +150,14 @@ boost::shared_ptr SuspendFlags::block(boost::weak_pt return res; } -boost::shared_ptr SuspendFlags::activate() +boost::shared_ptr SuspendFlags::activate(uint32_t sigmask) { SE_LOG_DEBUG(NULL, "SuspendFlags: (re)activating, currently %s", m_senderFD > 0 ? "active" : "inactive"); + if (m_senderFD > 0) { + return m_guard.lock(); + } + int fds[2]; if (pipe(fds)) { SE_THROW(StringPrintf("allocating pipe for signals failed: %s", strerror(errno))); @@ -163,8 +169,11 @@ boost::shared_ptr SuspendFlags::activate() m_receiverFD = fds[0]; SE_LOG_DEBUG(NULL, "SuspendFlags: activating signal handler(s) with fds %d->%d", m_senderFD, m_receiverFD); - sigaction(SIGINT, NULL, &m_oldSigInt); - sigaction(SIGTERM, NULL, &m_oldSigTerm); + for (int sig = 0; sig < 32; sig++) { + if (sigmask & (1< SuspendFlags::activate() // don't let processing of SIGINT be interrupted // of SIGTERM and vice versa, if we are doing the // handling - if (m_oldSigInt.sa_handler == SIG_DFL) { - sigaddset(&new_action.sa_mask, SIGINT); - } - if (m_oldSigTerm.sa_handler == SIG_DFL) { - sigaddset(&new_action.sa_mask, SIGTERM); - } - if (m_oldSigInt.sa_handler == SIG_DFL) { - sigaction(SIGINT, &new_action, NULL); - SE_LOG_DEBUG(NULL, "SuspendFlags: catch SIGINT"); + for (int sig = 0; sig < 32; sig++) { + if (sigmask & (1< guard(new GLibGuard(m_receiverFD)); + m_guard = guard; - return boost::shared_ptr(new GLibGuard(m_receiverFD)); + return guard; } void SuspendFlags::deactivate() @@ -196,14 +210,19 @@ void SuspendFlags::deactivate() SE_LOG_DEBUG(NULL, "SuspendFlags: deactivating fds %d->%d", m_senderFD, m_receiverFD); if (m_receiverFD >= 0) { - sigaction(SIGTERM, &m_oldSigTerm, NULL); - sigaction(SIGINT, &m_oldSigInt, NULL); + for (int sig = 0; sig < 32; sig++) { + if (m_activeSignals & (1<= 0) { - write(me.m_senderFD, &msg, 1); + unsigned char msg2[2] = { (unsigned char)(ABORT_MAX + sig), msg }; + write(me.m_senderFD, msg2, msg == ABORT_MAX ? 1 : 2); } } @@ -282,10 +306,13 @@ void SuspendFlags::printSignals() case ABORT_AGAIN: str = "Already aborting as requested earlier ..."; break; + default: { + int sig = msg - ABORT_MAX; + SE_LOG_DEBUG(NULL, "reveived signal %d", sig); + m_receivedSignals |= 1< activate(); + boost::shared_ptr activate(uint32_t sigmask = (1< m_guard; boost::weak_ptr m_suspendBlocker, m_abortBlocker; boost::shared_ptr block(boost::weak_ptr &blocker); }; -- cgit v1.2.3