Qore Programming Language 1.19.1
Loading...
Searching...
No Matches
QoreSignal.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 QoreSignal.h
4
5 Qore Programming Language
6
7 Copyright (C) 2003 - 2023 Qore Technologies, s.r.o.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26
27 Note that the Qore library is released under a choice of three open-source
28 licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
29 information.
30*/
31
32#ifdef HAVE_SIGNAL_HANDLING
33#ifndef _QORE_QORESIGNAL_H
34
35#define _QORE_QORESIGNAL_H
36
37#include <qore/QoreThreadLock.h>
38#include <qore/QoreCondition.h>
39#include <qore/QoreCounter.h>
40
41#include <csignal>
42#include <map>
43#include <string>
44
45// maximum number of signals
46#ifndef QORE_SIGNAL_MAX
47#ifdef NSIG
48#define QORE_SIGNAL_MAX (NSIG+1)
49#elif defined _NSIG
50#define QORE_SIGNAL_MAX _NSIG
51#elif defined _NSIGS
52#define QORE_SIGNAL_MAX _NSIGS
53#elif defined __DARWIN_NSIG
54#define QORE_SIGNAL_MAX (__DARWIN_NSIG+1)
55#else
56#error do not know maximum signal number on this platform
57#endif
58#endif
59
60// use SIGSYS for the status signal
61#define QORE_STATUS_SIGNAL SIGSYS
62
63class CodePgm {
64public:
66 QoreProgram* pgm;
67
68 DLLLOCAL void setProgram(QoreProgram* n_pgm) {
69 assert(n_pgm);
70 pgm = n_pgm;
71 pgm->ref();
72 //printd(5, "CodePgm::setProgram() pgm: %p %d -> %d\n", pgm, pgm->reference_count() - 1, pgm->reference_count());
73 }
74
75 DLLLOCAL CodePgm() : funcref(0), pgm(0) {
76 }
77
78 DLLLOCAL CodePgm(ResolvedCallReferenceNode* f, QoreProgram* p) : funcref(f), pgm(p) {
79 }
80
81 // must be called in the signal lock
82 DLLLOCAL void set(const ResolvedCallReferenceNode* n_funcref, QoreProgram* n_pgm) {
83 assert(!funcref);
84 assert(!pgm);
85
86 funcref = n_funcref->refRefSelf();
87 setProgram(n_pgm);
88 }
89
90 // must be called in the signal lock
91 DLLLOCAL CodePgm replace(const ResolvedCallReferenceNode* n_funcref, QoreProgram* n_pgm) {
92 assert(funcref);
93 assert(pgm);
94 assert(n_funcref);
95 CodePgm rv(funcref, pgm);
96
97 funcref = n_funcref->refRefSelf();
98 setProgram(n_pgm);
99 return rv;
100 }
101
102 // must be called in the signal lock
103 DLLLOCAL CodePgm take() {
104 assert(funcref);
105 CodePgm rv(funcref, pgm);
106 funcref = 0;
107 pgm = 0;
108 return rv;
109 }
110
111 DLLLOCAL void del(ExceptionSink* xsink) {
112 if (funcref) {
113 funcref->deref(xsink);
114 assert(pgm);
115 //printd(5, "CodePgm::del() pgm: %p %d -> %d\n", pgm, pgm->reference_count() + 1, pgm->reference_count());
116 pgm->deref(xsink);
117 }
118 }
119};
120
121class QoreSignalHandler : public CodePgm {
122public:
123 enum sh_status_e { SH_OK = 0, SH_InProgress = 1, SH_Delete = 2 };
124 sh_status_e status;
125
126 DLLLOCAL void init();
127 DLLLOCAL void runHandler(int sig, ExceptionSink* xsink);
128 DLLLOCAL bool isSet() const {
129 return (bool)funcref;
130 }
131 DLLLOCAL QoreProgram* getProgram() const {
132 return pgm;
133 }
134};
135
136// map of signals to module names
137typedef std::map<int, std::string> sig_map_t;
138
139class QoreSignalManager {
140 friend class QoreSignalManagerBusyHelper;
141
142private:
143 bool is_enabled; // signal handling enabled?
144 pthread_t ptid; // handler thread
145 int tid; // handler thread TID
146 QoreCounter tcount; // thread counter, for synchronization only
147 QoreCondition cond; // to ensure atomicity of set and remove calls
148 bool block;
149 int waiting;
150
151 DLLLOCAL void reload();
152 DLLLOCAL void stop_signal_thread_unlocked();
153 DLLLOCAL int start_signal_thread(ExceptionSink* xsink);
154 DLLLOCAL void stop_signal_thread();
155 DLLLOCAL void setMask(sigset_t& mask);
156
157public:
158 enum sig_cmd_e { C_None = 0, C_Reload = 1, C_Exit = 2 };
159
160 // set of signals we are managing
161 sigset_t mask;
162
163 // set of signals we do not manage (empty at start)
164 sig_map_t fmap;
165
166 int num_handlers;
167 bool thread_running;
168 QoreSignalHandler handlers[QORE_SIGNAL_MAX];
169 QoreThreadLock mutex;
170 sig_cmd_e cmd;
171
172 DLLLOCAL QoreSignalManager();
173 DLLLOCAL void init(bool disable_signal_mask = false);
174 DLLLOCAL void del();
175 DLLLOCAL int setHandler(int sig, const ResolvedCallReferenceNode* fr, ExceptionSink* xsink);
176 DLLLOCAL int removeHandler(int sig, ExceptionSink* xsink);
177 DLLLOCAL const char* getSignalName(int sig);
178 DLLLOCAL void signal_handler_thread();
179 DLLLOCAL void lock_idle();
180 DLLLOCAL void release_idle();
181 DLLLOCAL void start_handler();
182 DLLLOCAL void end_handler();
183 DLLLOCAL void preFork();
184 DLLLOCAL void postFork(bool new_process, ExceptionSink* xsink);
185 DLLLOCAL int q_gettid() {
186 return tid;
187 }
188 DLLLOCAL void reset_default_signal_mask();
189 DLLLOCAL bool running() { return tid != -1; }
190 DLLLOCAL bool enabled() { return is_enabled; }
191
192 // try to allow the signal to be managed externally (by a module)
193 // sig = signal number, name = name of module to manage signal
194 // returns 0 for OK, or an error string on error
195 DLLLOCAL QoreStringNode* reassignSignal(int sig, const char* name, bool reuse_sys = false);
196
197 // 0 = OK, -1 = no signals allocated (all or nothing)
198 DLLLOCAL QoreStringNode* reassignSignals(const sig_vec_t& sig_vec, const char* name, bool reuse_sys = false);
199
200 DLLLOCAL int releaseSignal(int sig, const char* name);
201
202 // 0 = OK, -1 = no signals release (all or nothing)
203 DLLLOCAL int releaseSignals(const sig_vec_t& sig_vec, const char* name);
204};
205
206DLLLOCAL extern QoreSignalManager QSM;
207
208#endif // _QORE_QORESIGNAL_H
209#endif // HAVE_SIGNAL_HANDLING
std::vector< int > sig_vec_t
signal vector
Definition: QoreLib.h:51
DLLLOCAL void ref() const
increments the reference count of the object
Definition: AbstractPrivateData.h:51
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
a thread condition class implementing a wrapper for pthread_cond_t
Definition: QoreCondition.h:45
a simple thread-safe counter object; objects can block on it until the counter reaches zero
Definition: QoreCounter.h:40
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:128
virtual DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count of the object
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
base class for resolved call references
Definition: CallReferenceNode.h:109
DLLLOCAL ResolvedCallReferenceNode * refRefSelf() const
references itself and returns this
Definition: CallReferenceNode.h:138
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
DLLEXPORT int q_gettid() noexcept
returns the current TID number