libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
SignalHandler.cc
Go to the documentation of this file.
1
2// -*- mode: c++; c-basic-offset:4 -*-
3
4// This file is part of libdap, A C++ implementation of the OPeNDAP Data
5// Access Protocol.
6
7// Copyright (c) 2002,2003 OPeNDAP, Inc.
8// Author: James Gallagher <jgallagher@opendap.org>
9//
10// This library is free software; you can redistribute it and/or
11// modify it under the terms of the GNU Lesser General Public
12// License as published by the Free Software Foundation; either
13// version 2.1 of the License, or (at your option) any later version.
14//
15// This library is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18// Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23//
24// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25
26// (c) COPYRIGHT URI/MIT 1994-2002
27// Please read the full copyright statement in the file COPYRIGHT_URI.
28//
29// Authors:
30// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31
32#include "config.h"
33
34#include <csignal>
35
36#include "SignalHandler.h"
37#include "util.h"
38
39namespace libdap {
40
41std::vector<EventHandler *> SignalHandler::d_signal_handlers{NSIG, nullptr};
42std::vector<Sigfunc *> SignalHandler::d_old_handlers{NSIG, nullptr};
43
53void SignalHandler::dispatcher(int signum) {
54 // Perform a sanity check...
55 if (d_signal_handlers[signum] != nullptr)
56 // Dispatch the handler's hook method.
57 d_signal_handlers[signum]->handle_signal(signum);
58
59 Sigfunc *old_handler = SignalHandler::d_old_handlers[signum];
60 if (old_handler == SIG_IGN || old_handler == SIG_ERR)
61 return;
62 else if (old_handler == SIG_DFL)
63 throw Error(internal_error, "Signal handler operation on an unsupported signal.");
64 else
65 old_handler(signum);
66}
67
73
86EventHandler *SignalHandler::register_handler(int signum, EventHandler *eh, bool ignore_by_default) {
87 // Check first for improper use.
88 switch (signum) {
89#ifndef WIN32
90 case SIGHUP:
91 case SIGKILL:
92 case SIGUSR1:
93 case SIGUSR2:
94 case SIGPIPE:
95 case SIGALRM:
96#endif
97 case SIGINT:
98 case SIGTERM:
99 break;
100
101 default:
102 throw InternalErr(__FILE__, __LINE__,
103 string("Call to register_handler with unsupported signal (") + long_to_string(signum) +
104 string(")."));
105 }
106
107 // Save the old EventHandler
108 EventHandler *old_eh = SignalHandler::d_signal_handlers[signum];
109
110 SignalHandler::d_signal_handlers[signum] = eh;
111
112 // Register the dispatcher to handle this signal. See Stevens, Advanced
113 // Programming in the UNIX Environment, p.298.
114#ifndef WIN32
115 struct sigaction sa {};
116 sa.sa_handler = dispatcher;
117 sigemptyset(&sa.sa_mask);
118 sa.sa_flags = 0;
119
120 // Try to suppress restarting system calls if we're handling an alarm.
121 // This lets alarms block I/O calls that would normally restart. 07/18/03
122 // jhrg
123 if (signum == SIGALRM) {
124#ifdef SA_INTERUPT
125 sa.sa_flags |= SA_INTERUPT;
126#endif
127 } else {
128#ifdef SA_RESTART
129 sa.sa_flags |= SA_RESTART;
130#endif
131 }
132
133 struct sigaction old_sa {}; // extract the old handler/action
134
135 if (sigaction(signum, &sa, &old_sa) < 0)
136 throw InternalErr(__FILE__, __LINE__, "Could not register a signal handler.");
137
138 // Take care of the case where this interface is used to register a
139 // handler more than once. We want to make sure that the dispatcher is
140 // not installed as the 'old handler' because that results in an infinite
141 // loop. 02/10/04 jhrg
142 if (ignore_by_default)
143 SignalHandler::d_old_handlers[signum] = SIG_IGN;
144 else if (old_sa.sa_handler != &dispatcher)
145 SignalHandler::d_old_handlers[signum] = old_sa.sa_handler;
146#endif // ndef WIN32
147
148 return old_eh;
149}
150
155 EventHandler *old_eh = SignalHandler::d_signal_handlers[signum];
156
157 SignalHandler::d_signal_handlers[signum] = nullptr;
158
159 return old_eh;
160}
161
162} // namespace libdap
#define internal_error
Internal server error (500)
Definition Error.h:63
A class for software fault reporting.
Definition InternalErr.h:61
static EventHandler * register_handler(int signum, EventHandler *eh, bool ignore_by_default=false)
static SignalHandler * instance()
static EventHandler * remove_handler(int signum)
top level DAP object to house generic methods
Definition AISConnect.cc:30
string long_to_string(long val, int base)
Definition util.cc:946
void Sigfunc(int)