GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
signal-wrappers.c
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2016-2017 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 // These functions may be provided by gnulib. We don't include gnulib
24 // headers directly in Octave's C++ source files to avoid problems that
25 // may be caused by the way that gnulib overrides standard library
26 // functions.
27 
28 #if defined (HAVE_CONFIG_H)
29 # include "config.h"
30 #endif
31 
32 #include <sys/types.h>
33 #include <signal.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #if defined (__WIN32__) && ! defined (__CYGWIN__)
38 # include <windows.h>
39 #else
40 # include <pthread.h>
41 #endif
42 
43 #include "signal-wrappers.h"
44 
45 int
46 octave_kill_wrapper (pid_t pid, int signum)
47 {
48 #if defined (HAVE_KILL)
49  return kill (pid, signum);
50 #else
51  return -1;
52 #endif
53 }
54 
55 char *
57 {
58  return strsignal (signum);
59 }
60 
61 bool
63 {
64 #if defined (HAVE_KILL)
65  return true;
66 #else
67  return false;
68 #endif
69 }
70 
71 bool
72 octave_get_sig_number (const char *signame, int *signum)
73 {
74  *signum = -1;
75 
76  // FIXME: this should probably use a perfect hash function.
77 
78  if (! strcmp (signame, "SIGINT"))
79  {
80 #if defined (SIGINT)
81  *signum = SIGINT;
82  return true;
83 #endif
84  }
85  else if (! strcmp (signame, "SIGBREAK"))
86  {
87 #if defined (SIGBREAK)
88  *signum = SIGBREAK;
89  return true;
90 #endif
91  }
92  else if (! strcmp (signame, "SIGABRT"))
93  {
94 #if defined (SIGABRT)
95  *signum = SIGABRT;
96  return true;
97 #endif
98  }
99  else if (! strcmp (signame, "SIGALRM"))
100  {
101 #if defined (SIGALRM)
102  *signum = SIGALRM;
103  return true;
104 #endif
105  }
106  else if (! strcmp (signame, "SIGBUS"))
107  {
108 #if defined (SIGBUS)
109  *signum = SIGBUS;
110  return true;
111 #endif
112  }
113  else if (! strcmp (signame, "SIGCHLD"))
114  {
115 #if defined (SIGCHLD)
116  *signum = SIGCHLD;
117  return true;
118 #endif
119  }
120  else if (! strcmp (signame, "SIGCLD"))
121  {
122 #if defined (SIGCLD)
123  *signum = SIGCLD;
124  return true;
125 #endif
126  }
127  else if (! strcmp (signame, "SIGCONT"))
128  {
129 #if defined (SIGCONT)
130  *signum = SIGCONT;
131  return true;
132 #endif
133  }
134  else if (! strcmp (signame, "SIGEMT"))
135  {
136 #if defined (SIGEMT)
137  *signum = SIGEMT;
138  return true;
139 #endif
140  }
141  else if (! strcmp (signame, "SIGFPE"))
142  {
143 #if defined (SIGFPE)
144  *signum = SIGFPE;
145  return true;
146 #endif
147  }
148  else if (! strcmp (signame, "SIGHUP"))
149  {
150 #if defined (SIGHUP)
151  *signum = SIGHUP;
152  return true;
153 #endif
154  }
155  else if (! strcmp (signame, "SIGILL"))
156  {
157 #if defined (SIGILL)
158  *signum = SIGILL;
159  return true;
160 #endif
161  }
162  else if (! strcmp (signame, "SIGINFO"))
163  {
164 #if defined (SIGINFO)
165  *signum = SIGINFO;
166  return true;
167 #endif
168  }
169  else if (! strcmp (signame, "SIGINT"))
170  {
171 #if defined (SIGINT)
172  *signum = SIGINT;
173  return true;
174 #endif
175  }
176  else if (! strcmp (signame, "SIGIOT"))
177  {
178 #if defined (SIGIOT)
179  *signum = SIGIOT;
180  return true;
181 #endif
182  }
183  else if (! strcmp (signame, "SIGLOST"))
184  {
185 #if defined (SIGLOST)
186  *signum = SIGLOST;
187  return true;
188 #endif
189  }
190  else if (! strcmp (signame, "SIGPIPE"))
191  {
192 #if defined (SIGPIPE)
193  *signum = SIGPIPE;
194  return true;
195 #endif
196  }
197  else if (! strcmp (signame, "SIGPOLL"))
198  {
199 #if defined (SIGPOLL)
200  *signum = SIGPOLL;
201  return true;
202 #endif
203  }
204  else if (! strcmp (signame, "SIGPROF"))
205  {
206 #if defined (SIGPROF)
207  *signum = SIGPROF;
208  return true;
209 #endif
210  }
211  else if (! strcmp (signame, "SIGPWR"))
212  {
213 #if defined (SIGPWR)
214  *signum = SIGPWR;
215  return true;
216 #endif
217  }
218  else if (! strcmp (signame, "SIGQUIT"))
219  {
220 #if defined (SIGQUIT)
221  *signum = SIGQUIT;
222  return true;
223 #endif
224  }
225  else if (! strcmp (signame, "SIGSEGV"))
226  {
227 #if defined (SIGSEGV)
228  *signum = SIGSEGV;
229  return true;
230 #endif
231  }
232  else if (! strcmp (signame, "SIGSTOP"))
233  {
234 #if defined (SIGSTOP)
235  *signum = SIGSTOP;
236  return true;
237 #endif
238  }
239  else if (! strcmp (signame, "SIGSYS"))
240  {
241 #if defined (SIGSYS)
242  *signum = SIGSYS;
243  return true;
244 #endif
245  }
246  else if (! strcmp (signame, "SIGTERM"))
247  {
248 #if defined (SIGTERM)
249  *signum = SIGTERM;
250  return true;
251 #endif
252  }
253  else if (! strcmp (signame, "SIGTRAP"))
254  {
255 #if defined (SIGTRAP)
256  *signum = SIGTRAP;
257  return true;
258 #endif
259  }
260  else if (! strcmp (signame, "SIGTSTP"))
261  {
262 #if defined (SIGTSTP)
263  *signum = SIGTSTP;
264  return true;
265 #endif
266  }
267  else if (! strcmp (signame, "SIGTTIN"))
268  {
269 #if defined (SIGTTIN)
270  *signum = SIGTTIN;
271  return true;
272 #endif
273  }
274  else if (! strcmp (signame, "SIGTTOU"))
275  {
276 #if defined (SIGTTOU)
277  *signum = SIGTTOU;
278  return true;
279 #endif
280  }
281  else if (! strcmp (signame, "SIGURG"))
282  {
283 #if defined (SIGURG)
284  *signum = SIGURG;
285  return true;
286 #endif
287  }
288  else if (! strcmp (signame, "SIGUSR1"))
289  {
290 #if defined (SIGUSR1)
291  *signum = SIGUSR1;
292  return true;
293 #endif
294  }
295  else if (! strcmp (signame, "SIGUSR2"))
296  {
297 #if defined (SIGUSR2)
298  *signum = SIGUSR2;
299  return true;
300 #endif
301  }
302  else if (! strcmp (signame, "SIGVTALRM"))
303  {
304 #if defined (SIGVTALRM)
305  *signum = SIGVTALRM;
306  return true;
307 #endif
308  }
309  else if (! strcmp (signame, "SIGIO"))
310  {
311 #if defined (SIGIO)
312  *signum = SIGIO;
313  return true;
314 #endif
315  }
316  else if (! strcmp (signame, "SIGWINCH"))
317  {
318 #if defined (SIGWINCH)
319  *signum = SIGWINCH;
320  return true;
321 #endif
322  }
323  else if (! strcmp (signame, "SIGXCPU"))
324  {
325 #if defined (SIGXCPU)
326  *signum = SIGXCPU;
327  return true;
328 #endif
329  }
330  else if (! strcmp (signame, "SIGXFSZ"))
331  {
332 #if defined (SIGXFSZ)
333  *signum = SIGXFSZ;
334  return true;
335 #endif
336  }
337 
338  return false;
339 }
340 
343  bool restart_syscalls)
344 {
345  struct sigaction act, oact;
346 
347  act.sa_handler = handler;
348  act.sa_flags = 0;
349 
350 #if defined (SIGALRM)
351  if (sig == SIGALRM)
352  {
353 # if defined (SA_INTERRUPT)
354  act.sa_flags |= SA_INTERRUPT;
355 # endif
356  }
357 #endif
358 #if defined (SA_RESTART)
359 # if defined (SIGALRM)
360  else
361 # endif
362  // FIXME: Do we also need to explicitly disable SA_RESTART?
363  if (restart_syscalls)
364  act.sa_flags |= SA_RESTART;
365 #endif
366 
367  sigemptyset (&act.sa_mask);
368  sigemptyset (&oact.sa_mask);
369 
370  sigaction (sig, &act, &oact);
371 
372  return oact.sa_handler;
373 }
374 
377  octave_sig_handler *handler,
378  bool restart_syscalls)
379 {
380  int sig;
381 
382  return (octave_get_sig_number (signame, &sig)
383  ? octave_set_signal_handler_internal (sig, handler, restart_syscalls)
384  : 0);
385 }
386 
387 int
389 {
390  return NSIG;
391 }
392 
393 typedef struct
394 {
395  sigset_t nvar;
396  sigset_t ovar;
397 } sigset_info;
398 
399 void *
401 {
402 #if defined (SIGCHLD)
403 
405 
406  if (context)
407  {
408  sigemptyset (&(context->nvar));
409  sigaddset (&(context->nvar), SIGCHLD);
410  sigemptyset (&(context->ovar));
411  sigprocmask (SIG_BLOCK, &(context->nvar), &(context->ovar));
412  }
413 
414  return context;
415 
416 #else
417 
418  return 0;
419 
420 #endif
421 }
422 
423 void
424 octave_unblock_child (void *context_arg)
425 {
426  if (context_arg)
427  {
428  sigset_info *context = (sigset_info *) context_arg;
429 
430  sigprocmask (SIG_SETMASK, &(context->ovar), 0);
431 
432  free (context);
433  }
434 }
435 
436 static void
437 block_or_unblock_signal (int how, int sig)
438 {
439 #if ! defined (__WIN32__) || defined (__CYGWIN__)
440  // Blocking/unblocking signals at thread level is only supported
441  // on platform with fully compliant POSIX threads. This is not
442  // supported on Win32. Moreover, we have to make sure that SIGINT
443  // handler is not installed before calling AllocConsole: installing
444  // a SIGINT handler internally calls SetConsoleCtrlHandler, which
445  // must be called after AllocConsole to be effective.
446 
447  sigset_t signal_mask;
448 
449  sigemptyset (&signal_mask);
450 
451  sigaddset (&signal_mask, sig);
452 
453  pthread_sigmask (how, &signal_mask, 0);
454 #endif
455 }
456 
457 void
459 {
460  block_or_unblock_signal (SIG_BLOCK, SIGINT);
461 }
462 
463 void
465 {
466  block_or_unblock_signal (SIG_UNBLOCK, SIGINT);
467 }
468 
469 
470 /* Allow us to save the signal mask and then restore it to the most
471  recently saved value. This is necessary when using the POSIX signal
472  handling interface on some systems calling longjmp out of the signal
473  handler to get to the top level on an interrupt doesn't restore the
474  original signal mask. Alternatively, we could use
475  sigsetjmp/siglongjmp, but saving and restoring the signal mask
476  ourselves works ok and seems simpler just now. */
477 
478 static sigset_t octave_signal_mask;
479 
480 void
482 {
483  sigprocmask (0, 0, &octave_signal_mask);
484 }
485 
486 void
488 {
489  sigprocmask (SIG_SETMASK, &octave_signal_mask, 0);
490 }
491 
492 int
494 {
495  return raise (signum);
496 }
static void block_or_unblock_signal(int how, int sig)
int kill(pid_t pid, int sig)
int octave_kill_wrapper(pid_t pid, int signum)
void octave_restore_signal_mask(void)
octave_sig_handler * octave_set_signal_handler_internal(int sig, octave_sig_handler *handler, bool restart_syscalls)
void * octave_block_child(void)
void octave_sig_handler(int)
void octave_unblock_child(void *context_arg)
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:76
double signum(double x)
Definition: lo-mappers.h:259
bool strcmp(const T &str_a, const T &str_b)
True if strings are the same.
Definition: oct-string.cc:112
void octave_block_interrupt_signal(void)
void octave_save_signal_mask(void)
int octave_num_signals(void)
bool octave_have_kill(void)
int octave_raise_wrapper(int signum)
static sigset_t octave_signal_mask
void octave_unblock_interrupt_signal(void)
void free(void *)
bool octave_get_sig_number(const char *signame, int *signum)
octave_sig_handler * octave_set_signal_handler_by_name(const char *signame, octave_sig_handler *handler, bool restart_syscalls)
void * malloc(size_t)
char * octave_strsignal_wrapper(int signum)