GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
cxx-signal-helpers.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2016-2025 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <sys/types.h>
31#include <signal.h>
32#include <stdlib.h>
33#include <string.h>
34
35#if defined (__WIN32__) && ! defined (__CYGWIN__)
36# include <windows.h>
37#else
38# include <pthread.h>
39#endif
40
41#include "signal-wrappers.h"
42
43#if ! defined (__WIN32__) || defined (__CYGWIN__)
44
45// The following pattern often used in C code to initialize a static
46// variable could possibly cause trouble in multi-threaded code:
47//
48// TYPE * get_var () {
49// static bool initialized = false;
50// static TYPE *var;
51// if (! initialized) {
52// var = ...;
53// initialized = true;
54// }
55// return var;
56// }
57//
58// Changing this code to
59//
60// static TYPE *var = init_var ();
61//
62// doesn't work in C because the static variable can't be initialized by
63// a function call. So we have to do this job in C++. To avoid calling
64// new, initialize sigset_t rather than a pointer to allocated storage.
65
66static sigset_t
67init_async_signals ()
68{
69 sigset_t sigmask;
70
71 sigemptyset (&sigmask);
72
73 // The signals listed here should match the list of signals that
74 // we handle in the signal handler thread.
75
76 // Interrupt signals.
77
78#if defined (SIGINT)
79 sigaddset (&sigmask, SIGINT);
80#endif
81
82#if defined (SIGBREAK)
83 sigaddset (&sigmask, SIGBREAK);
84#endif
85
86 // Termination signals.
87
88#if defined (SIGHUP)
89 sigaddset (&sigmask, SIGHUP);
90#endif
91
92#if defined (SIGQUIT)
93 sigaddset (&sigmask, SIGQUIT);
94#endif
95
96#if defined (SIGTERM)
97 sigaddset (&sigmask, SIGTERM);
98#endif
99
100 // Alarm signals.
101
102#if defined (SIGALRM)
103 sigaddset (&sigmask, SIGALRM);
104#endif
105
106#if defined (SIGVTALRM)
107 sigaddset (&sigmask, SIGVTALRM);
108#endif
109
110 // I/O signals.
111
112#if defined (SIGLOST)
113 sigaddset (&sigmask, SIGLOST);
114#endif
115
116#if defined (SIGPIPE)
117 sigaddset (&sigmask, SIGPIPE);
118#endif
119
120 // Job control signals.
121
122#if defined (SIGCHLD)
123 sigaddset (&sigmask, SIGCHLD);
124#endif
125
126#if defined (SIGCLD)
127 sigaddset (&sigmask, SIGCLD);
128#endif
129
130 // Resource limit signals.
131
132#if defined (SIGXCPU)
133 sigaddset (&sigmask, SIGXCPU);
134#endif
135
136#if defined (SIGXFSZ)
137 sigaddset (&sigmask, SIGXFSZ);
138#endif
139
140 return sigmask;
141}
142
143// Initialized once, is const so we never write to it again and it can
144// be accessed by multiple threads without locking.
145
146static const sigset_t async_signals = init_async_signals ();
147
148#endif
149
150void
152{
153#if ! defined (__WIN32__) || defined (__CYGWIN__)
154 pthread_sigmask (SIG_BLOCK, &async_signals, 0);
155#endif
156}
157
158void
160{
161#if ! defined (__WIN32__) || defined (__CYGWIN__)
162 pthread_sigmask (SIG_UNBLOCK, &async_signals, 0);
163#endif
164}
165
166#if ! defined (__WIN32__) || defined (__CYGWIN__)
167
168static void *
169signal_watcher (void *arg)
170{
171 octave_sig_handler *handler = reinterpret_cast<octave_sig_handler *> (arg);
172
174
175 while (1)
176 {
177 int sig_caught;
178
179 if (sigwait (&async_signals, &sig_caught))
180 {
181 // FIXME: what else should we do?
182 abort ();
183 }
184
185 // Let handler have complete control over what to do.
186 (*handler) (sig_caught);
187 }
188}
189
190#endif
191
192void
194{
195#if ! defined (__WIN32__)
196 pthread_t sighandler_thread_id;
197
198 if (pthread_create (&sighandler_thread_id, 0, signal_watcher,
199 reinterpret_cast<void *> (handler)))
200 {
201 // FIXME: what else should we do?
202 abort ();
203 }
204#else
206
207 octave_unused_parameter (handler);
208#endif
209}
void octave_create_interrupt_watcher_thread(octave_sig_handler *handler)
void octave_unblock_async_signals()
void octave_block_async_signals()
void octave_sig_handler(int)