diff options
author | Karl Berry <karl@freefriends.org> | 2018-01-17 22:50:15 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2018-01-17 22:50:15 +0000 |
commit | e7dfe5ab98e759081fc73990ed6c1ac6910a105d (patch) | |
tree | 1635f79c86856a6aa57a45b8b952b651ef9fcba9 /Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp | |
parent | ae542350b1e3add10d4ee3d7b68f610132f31a50 (diff) |
dvisvgm 2.3.1 (patched)
git-svn-id: svn://tug.org/texlive/trunk@46352 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp')
-rw-r--r-- | Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp index 696c99ac18d..988ec8d19a5 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/SignalHandler.cpp @@ -2,7 +2,7 @@ ** SignalHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2017 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -23,13 +23,38 @@ #include <csignal> #include <cstdlib> #include "SignalHandler.hpp" +#include "utility.hpp" using namespace std; -bool SignalHandler::_break = false; +volatile bool SignalHandler::_break = false; + +/** Helper class that encapsulates the system-specific parts of + * registering and handling CTRL-C (SIGINT) events. */ +class SignalHandler::Impl { + using HandlerFunc = void (*)(int); + public: + Impl (); + bool setSigintHandler (HandlerFunc handler); + bool restoreSigintHandler (); + + private: +#ifdef HAVE_SIGACTION + struct sigaction _currentSigaction; + struct sigaction _origSigaction; +#else + HandlerFunc _origHandlerFunc; +#endif +}; + + +SignalHandler::SignalHandler () + : _active(false), _impl(util::make_unique<SignalHandler::Impl>()) +{ +} -SignalHandler::~SignalHandler() { +SignalHandler::~SignalHandler () { stop(); } @@ -46,19 +71,17 @@ SignalHandler& SignalHandler::instance() { bool SignalHandler::start () { if (!_active) { _break = false; - if (signal(SIGINT, SignalHandler::callback) != SIG_ERR) { + if (_impl->setSigintHandler(callback)) _active = true; - return true; - } } - return false; + return _active; } /** Stops listening for CTRL-C signals. */ void SignalHandler::stop () { if (_active) { - signal(SIGINT, SIG_DFL); + _impl->restoreSigintHandler(); _active = false; } } @@ -84,3 +107,47 @@ void SignalHandler::callback (int) { _break = true; } + +// Prefer sigaction() to signal() due to its more reliable interface and behavior. +// Use signal() as fallback on systems that don't provide sigaction(). + +#ifdef HAVE_SIGACTION + +SignalHandler::Impl::Impl () { + _origSigaction.sa_handler = nullptr; +} + + +bool SignalHandler::Impl::setSigintHandler (HandlerFunc handler) { + sigemptyset(&_currentSigaction.sa_mask); + _currentSigaction.sa_handler = handler; + _currentSigaction.sa_flags = SA_SIGINFO; + return (sigaction(SIGINT, &_currentSigaction, &_origSigaction) == 0); +} + + +bool SignalHandler::Impl::restoreSigintHandler () { + if (_origSigaction.sa_handler == nullptr) + return false; + return (sigaction(SIGINT, &_origSigaction, 0) == 0); +} + +#else // !HAVE_SIGACTION + +SignalHandler::Impl::Impl () : _origHandlerFunc(SIG_ERR) { +} + + +bool SignalHandler::Impl::setSigintHandler (HandlerFunc handler) { + _origHandlerFunc = signal(SIGINT, handler); + return _origHandlerFunc != SIG_ERR; +} + + +bool SignalHandler::Impl::restoreSigintHandler () { + if (_origHandlerFunc == SIG_ERR) + return false; + return (signal(SIGINT, _origHandlerFunc) != SIG_ERR); +} + +#endif |