Overview
Features
Download
Documentation
Community
Add-Ons & Services

SignalHandler: catch ctrl-c (SIGINT)

General discussion regarding the development of POCO for contributors.

SignalHandler: catch ctrl-c (SIGINT)

Postby Rabenklaue » 03 Feb 2010, 00:14

As I did not find any way (except the waitForTermination() method in ServerApplication) to handle SIGINT (CTRL-C) signals in an aspired way on Linux (to ensure all destructors will be called or extra clean-up routines may be called), I inherited Poco::SignalHandler to handle those in a very similar way the actual implementation of SignalHandler does. Perhaps it is useful for anybody or could even be added to Poco (e.g. abstracting the waitForTermination() in a more C++ like way).

Code: Select all
#include <Poco/SignalHandler.h>
#include <Poco/Exception.h>

#if defined(POCO_OS_FAMILY_UNIX)
#include <csignal>
#include <cstdlib>

POCO_DECLARE_EXCEPTION(Foundation_API, SignalExceptionTerm, Poco::LogicException);
POCO_IMPLEMENT_EXCEPTION(SignalExceptionTerm, Poco::LogicException, "Signal received");

class SignalHandlerTerm : public Poco::SignalHandler {
public:

   SignalHandlerTerm() {
      JumpBufferVec& jbv = jumpBufferVec();
      JumpBuffer buf;
      jbv.push_back(buf);
   }

   ~SignalHandlerTerm() {
      jumpBufferVec().pop_back();
   }

   static void throwSignalException(int sig) {
      switch (sig) {
         case SIGINT:
            throw SignalExceptionTerm("Interrupt");
         case SIGTERM:
            throw SignalExceptionTerm("Termination");
      }
   }

   static void install() {
#ifndef POCO_NO_SIGNAL_HANDLER
      struct sigaction sa;
      sa.sa_handler = handleSignal;
      sa.sa_flags   = 0;
      sigemptyset(&sa.sa_mask);
      sigaction(SIGINT, &sa, 0);
      sigaction(SIGTERM, &sa, 0);
#endif
   }

   static void handleSignal(int sig) {
      JumpBufferVec& jb = jumpBufferVec();
      if (!jb.empty())
         siglongjmp(jb.back().buf, sig);

      // Abort if no jump buffer registered
      std::abort();
   }

private:
   friend class ThreadImpl;
   static JumpBufferVec _jumpBufferVec;
};

SignalHandlerTerm::JumpBufferVec SignalHandlerTerm::_jumpBufferVec;

#define throw_on_exit \
   SignalHandlerTerm signal_handler_term; \
   SignalHandlerTerm::install(); \
   int _term_signal = sigsetjmp(signal_handler_term.jumpBuffer(), 1); \
   if (_term_signal) signal_handler_term.throwSignalException(_term_signal);
#else
#define throw_on_exit
#endif // POCO_OS_FAMILY_UNIX


int main(int argc, char** argv) {
   try {
      throw_on_exit;
      sleep(100);
   }
#if defined(POCO_OS_FAMILY_UNIX)
   catch (SignalExceptionTerm& exc) {
      LogDebug(Poco::Logger::get("Main"), "Stop Application: " << exc.displayText());
      return Poco::Util::Application::EXIT_OK;
   }
#else
   catch(...) {}
#endif // POCO_OS_FAMILY_UNIX

   return Poco::Util::Application::EXIT_OK;
}
Rabenklaue
 
Posts: 10
Joined: 22 Jan 2010, 07:08
Location: Germany

Re: SignalHandler: catch ctrl-c (SIGINT)

Postby Rabenklaue » 10 Feb 2010, 14:20

Btw: In SignalHandler.cpp the

#include <signal.h>

should be changed to

#include <csignal> (seems more C++ conform)

Except that, why is SignalHandler only available for UNIX platforms (regarding the #ifdefs in the source)? As seen on MSDN it shall be available on Windows platforms as well.

Stefan
Rabenklaue
 
Posts: 10
Joined: 22 Jan 2010, 07:08
Location: Germany


Return to Contributors

Who is online

Users browsing this forum: No registered users and 0 guests