Blame SignalHandler.h

Packit a4aae4
Packit a4aae4
// -*- mode: c++; c-basic-offset:4 -*-
Packit a4aae4
Packit a4aae4
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
Packit a4aae4
// Access Protocol.
Packit a4aae4
Packit a4aae4
// Copyright (c) 2002,2003 OPeNDAP, Inc.
Packit a4aae4
// Author: James Gallagher <jgallagher@opendap.org>
Packit a4aae4
//
Packit a4aae4
// This library is free software; you can redistribute it and/or
Packit a4aae4
// modify it under the terms of the GNU Lesser General Public
Packit a4aae4
// License as published by the Free Software Foundation; either
Packit a4aae4
// version 2.1 of the License, or (at your option) any later version.
Packit a4aae4
//
Packit a4aae4
// This library is distributed in the hope that it will be useful,
Packit a4aae4
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4aae4
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a4aae4
// Lesser General Public License for more details.
Packit a4aae4
//
Packit a4aae4
// You should have received a copy of the GNU Lesser General Public
Packit a4aae4
// License along with this library; if not, write to the Free Software
Packit a4aae4
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit a4aae4
//
Packit a4aae4
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
Packit a4aae4
Packit a4aae4
#ifndef signal_handler_h
Packit a4aae4
#define signal_handler_h
Packit a4aae4
Packit a4aae4
#include <signal.h>
Packit a4aae4
Packit a4aae4
#include "EventHandler.h"
Packit a4aae4
#include "InternalErr.h"
Packit a4aae4
Packit a4aae4
namespace libdap
Packit a4aae4
{
Packit a4aae4
Packit a4aae4
typedef void Sigfunc(int); // Plauger, 1992
Packit a4aae4
Packit a4aae4
/** Singleton to handle signals. This class adapts the C-style function call
Packit a4aae4
    interface to one suited for C++. This class records a signal's old
Packit a4aae4
    action/handler when it installs new handler. When a signal is caught, the
Packit a4aae4
    new handler (registered with this class) is run and then the old
Packit a4aae4
    action/handler is performed. This ensures that when libdap++ is embedded
Packit a4aae4
    in code which has a handler for a signal such as SIGINT which does
Packit a4aae4
    something other than the default, that thing, whatever it may be, gets
Packit a4aae4
    done.
Packit a4aae4
Packit a4aae4
    This class treats signals it registers (using the EventHandler abstract
Packit a4aae4
    class) differently than ones registered using the \c signal() or \c
Packit a4aae4
    sigaction() system interfaces. If the register_handler() method is called
Packit a4aae4
    and an instance of EventHandler is already bound to \e signum, then the
Packit a4aae4
    old EventHandler is returned. However, if there's an existing handler
Packit a4aae4
    that was set up with \c sigaction(), ..., it won't be returned. Instead
Packit a4aae4
    it will either be run after the newly registered EventHandler or ignored,
Packit a4aae4
    depending on register_handler()'s \e override parameter. This feature may
Packit a4aae4
    be used only for POSIX.1 signals which cause process termination. They
Packit a4aae4
    are: SIGHUP, SIGINT, SIGKILL, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, and
Packit a4aae4
    SIGUSR2.
Packit a4aae4
Packit a4aae4
    @note Based on "Applying Design Patterns to Simplify Signal Handling",
Packit a4aae4
    Douglas C. Schmidt, 1998,
Packit a4aae4
    http://www.cs.wustl.edu/~schmidt/signal-patterns.html.
Packit a4aae4
Packit a4aae4
    @see EventHandler
Packit a4aae4
    @author James Gallagher <jgallagher@opendap.org> */
Packit a4aae4
class SignalHandler
Packit a4aae4
{
Packit a4aae4
private:
Packit a4aae4
    // Ensure we're a Singleton.
Packit a4aae4
    SignalHandler() {}
Packit a4aae4
    SignalHandler(const SignalHandler &) {}
Packit a4aae4
Packit a4aae4
    // Singleton pointer.
Packit a4aae4
    static SignalHandler *d_instance;
Packit a4aae4
Packit a4aae4
    // Table of pointers to instances of EventHandlers. Since EventHandler is
Packit a4aae4
    // abstract, the pointers will actually reference instances that are
Packit a4aae4
    // children of EventHandler. NSIG is defined in signal.h but this may be
Packit a4aae4
    // a portability issue.
Packit a4aae4
    static EventHandler *d_signal_handlers[NSIG];
Packit a4aae4
Packit a4aae4
    // This array holds the old signal handlers. Once the handler in
Packit a4aae4
    // d_signal_handler[signum] is run, look here to see what the original
Packit a4aae4
    // action was. This is important since libdap++ is often embedded in code
Packit a4aae4
    // that already has a non-default signal handler for things like SIGINT.
Packit a4aae4
    static Sigfunc *d_old_handlers[NSIG];
Packit a4aae4
Packit a4aae4
    // Entry point adapter installed into sigaction(). This must be a static
Packit a4aae4
    // method (or a regular C-function) to conform to sigaction's interface.
Packit a4aae4
    // this is the part of SignalHandler that uses the Adapter pattern.
Packit a4aae4
    static void dispatcher(int signum);
Packit a4aae4
Packit a4aae4
    // Delete the global instance. Call this with atexit().
Packit a4aae4
    static void delete_instance();
Packit a4aae4
Packit a4aae4
    // Call this using pthread_once() to ensure there's only one instance
Packit a4aae4
    // when running in a MT world.
Packit a4aae4
    static void initialize_instance();
Packit a4aae4
Packit a4aae4
    friend class SignalHandlerTest;
Packit a4aae4
    friend class HTTPCacheTest;
Packit a4aae4
Packit a4aae4
public:
Packit a4aae4
    static SignalHandler *instance();
Packit a4aae4
Packit a4aae4
    ///
Packit a4aae4
    virtual ~SignalHandler() {}
Packit a4aae4
Packit a4aae4
    EventHandler *register_handler(int signum, EventHandler *eh,
Packit a4aae4
                                   bool override = false);
Packit a4aae4
Packit a4aae4
    EventHandler *remove_handler(int signum);
Packit a4aae4
};
Packit a4aae4
Packit a4aae4
} // namespace libdap
Packit a4aae4
Packit a4aae4
#endif // signal_handler_h