Mercurial > octave
view liboctave/wrappers/signal-wrappers.c @ 23084:ef4d915df748
maint: Merge stable to default.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Mon, 23 Jan 2017 14:27:48 -0500 |
parents | 3a2b891d0b33 e9a0469dedd9 |
children | 092078913d54 |
line wrap: on
line source
/* Copyright (C) 2016 John W. Eaton This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ // These functions may be provided by gnulib. We don't include gnulib // headers directly in Octave's C++ source files to avoid problems that // may be caused by the way that gnulib overrides standard library // functions. #if defined (HAVE_CONFIG_H) # include "config.h" #endif #include <sys/types.h> #include <signal.h> #include <stdlib.h> #include <string.h> #if defined (__WIN32__) && ! defined (__CYGWIN__) # include <windows.h> #else # include <pthread.h> #endif #include "signal-wrappers.h" int octave_kill_wrapper (pid_t pid, int signum) { #if defined (HAVE_KILL) return kill (pid, signum); #else return -1; #endif } char * octave_strsignal_wrapper (int signum) { return strsignal (signum); } bool octave_have_kill (void) { #if defined (HAVE_KILL) return true; #else return false; #endif } bool octave_get_sig_number (const char *signame, int *signum) { *signum = -1; // FIXME: this should probably use a perfect hash function. if (! strcmp (signame, "SIGINT")) { #if defined (SIGINT) *signum = SIGINT; return true; #endif } else if (! strcmp (signame, "SIGBREAK")) { #if defined (SIGBREAK) *signum = SIGBREAK; return true; #endif } else if (! strcmp (signame, "SIGABRT")) { #if defined (SIGABRT) *signum = SIGABRT; return true; #endif } else if (! strcmp (signame, "SIGALRM")) { #if defined (SIGALRM) *signum = SIGALRM; return true; #endif } else if (! strcmp (signame, "SIGBUS")) { #if defined (SIGBUS) *signum = SIGBUS; return true; #endif } else if (! strcmp (signame, "SIGCHLD")) { #if defined (SIGCHLD) *signum = SIGCHLD; return true; #endif } else if (! strcmp (signame, "SIGCLD")) { #if defined (SIGCLD) *signum = SIGCLD; return true; #endif } else if (! strcmp (signame, "SIGCONT")) { #if defined (SIGCONT) *signum = SIGCONT; return true; #endif } else if (! strcmp (signame, "SIGEMT")) { #if defined (SIGEMT) *signum = SIGEMT; return true; #endif } else if (! strcmp (signame, "SIGFPE")) { #if defined (SIGFPE) *signum = SIGFPE; return true; #endif } else if (! strcmp (signame, "SIGHUP")) { #if defined (SIGHUP) *signum = SIGHUP; return true; #endif } else if (! strcmp (signame, "SIGILL")) { #if defined (SIGILL) *signum = SIGILL; return true; #endif } else if (! strcmp (signame, "SIGINFO")) { #if defined (SIGINFO) *signum = SIGINFO; return true; #endif } else if (! strcmp (signame, "SIGINT")) { #if defined (SIGINT) *signum = SIGINT; return true; #endif } else if (! strcmp (signame, "SIGIOT")) { #if defined (SIGIOT) *signum = SIGIOT; return true; #endif } else if (! strcmp (signame, "SIGLOST")) { #if defined (SIGLOST) *signum = SIGLOST; return true; #endif } else if (! strcmp (signame, "SIGPIPE")) { #if defined (SIGPIPE) *signum = SIGPIPE; return true; #endif } else if (! strcmp (signame, "SIGPOLL")) { #if defined (SIGPOLL) *signum = SIGPOLL; return true; #endif } else if (! strcmp (signame, "SIGPROF")) { #if defined (SIGPROF) *signum = SIGPROF; return true; #endif } else if (! strcmp (signame, "SIGPWR")) { #if defined (SIGPWR) *signum = SIGPWR; return true; #endif } else if (! strcmp (signame, "SIGQUIT")) { #if defined (SIGQUIT) *signum = SIGQUIT; return true; #endif } else if (! strcmp (signame, "SIGSEGV")) { #if defined (SIGSEGV) *signum = SIGSEGV; return true; #endif } else if (! strcmp (signame, "SIGSTOP")) { #if defined (SIGSTOP) *signum = SIGSTOP; return true; #endif } else if (! strcmp (signame, "SIGSYS")) { #if defined (SIGSYS) *signum = SIGSYS; return true; #endif } else if (! strcmp (signame, "SIGTERM")) { #if defined (SIGTERM) *signum = SIGTERM; return true; #endif } else if (! strcmp (signame, "SIGTRAP")) { #if defined (SIGTRAP) *signum = SIGTRAP; return true; #endif } else if (! strcmp (signame, "SIGTSTP")) { #if defined (SIGTSTP) *signum = SIGTSTP; return true; #endif } else if (! strcmp (signame, "SIGTTIN")) { #if defined (SIGTTIN) *signum = SIGTTIN; return true; #endif } else if (! strcmp (signame, "SIGTTOU")) { #if defined (SIGTTOU) *signum = SIGTTOU; return true; #endif } else if (! strcmp (signame, "SIGURG")) { #if defined (SIGURG) *signum = SIGURG; return true; #endif } else if (! strcmp (signame, "SIGUSR1")) { #if defined (SIGUSR1) *signum = SIGUSR1; return true; #endif } else if (! strcmp (signame, "SIGUSR2")) { #if defined (SIGUSR2) *signum = SIGUSR2; return true; #endif } else if (! strcmp (signame, "SIGVTALRM")) { #if defined (SIGVTALRM) *signum = SIGVTALRM; return true; #endif } else if (! strcmp (signame, "SIGIO")) { #if defined (SIGIO) *signum = SIGIO; return true; #endif } else if (! strcmp (signame, "SIGWINCH")) { #if defined (SIGWINCH) *signum = SIGWINCH; return true; #endif } else if (! strcmp (signame, "SIGXCPU")) { #if defined (SIGXCPU) *signum = SIGXCPU; return true; #endif } else if (! strcmp (signame, "SIGXFSZ")) { #if defined (SIGXFSZ) *signum = SIGXFSZ; return true; #endif } return false; } octave_sig_handler * octave_set_signal_handler_internal (int sig, octave_sig_handler *handler, bool restart_syscalls) { struct sigaction act, oact; act.sa_handler = handler; act.sa_flags = 0; #if defined (SIGALRM) if (sig == SIGALRM) { # if defined (SA_INTERRUPT) act.sa_flags |= SA_INTERRUPT; # endif } #endif #if defined (SA_RESTART) # if defined (SIGALRM) else # endif // FIXME: Do we also need to explicitly disable SA_RESTART? if (restart_syscalls) act.sa_flags |= SA_RESTART; #endif sigemptyset (&act.sa_mask); sigemptyset (&oact.sa_mask); sigaction (sig, &act, &oact); return oact.sa_handler; } octave_sig_handler * octave_set_signal_handler_by_name (const char *signame, octave_sig_handler *handler, bool restart_syscalls) { int sig; return (octave_get_sig_number (signame, &sig) ? octave_set_signal_handler_internal (sig, handler, restart_syscalls) : 0); } int octave_num_signals (void) { return NSIG; } typedef struct { sigset_t nvar; sigset_t ovar; } sigset_info; void * octave_block_child (void) { #if defined (SIGCHLD) sigset_info *context = (sigset_info *) malloc (sizeof (sigset_info)); if (context) { sigemptyset (&(context->nvar)); sigaddset (&(context->nvar), SIGCHLD); sigemptyset (&(context->ovar)); sigprocmask (SIG_BLOCK, &(context->nvar), &(context->ovar)); } return context; #else return 0; #endif } void octave_unblock_child (void *context_arg) { if (context_arg) { sigset_info *context = (sigset_info *) context_arg; sigprocmask (SIG_SETMASK, &(context->ovar), 0); free (context); } } static void block_or_unblock_signal (int how, int sig) { #if ! defined (__WIN32__) || defined (__CYGWIN__) // Blocking/unblocking signals at thread level is only supported // on platform with fully compliant POSIX threads. This is not // supported on Win32. Moreover, we have to make sure that SIGINT // handler is not installed before calling AllocConsole: installing // a SIGINT handler internally calls SetConsoleCtrlHandler, which // must be called after AllocConsole to be effective. sigset_t signal_mask; sigemptyset (&signal_mask); sigaddset (&signal_mask, sig); pthread_sigmask (how, &signal_mask, 0); #endif } void octave_block_interrupt_signal (void) { block_or_unblock_signal (SIG_BLOCK, SIGINT); } void octave_unblock_interrupt_signal (void) { block_or_unblock_signal (SIG_UNBLOCK, SIGINT); } /* Allow us to save the signal mask and then restore it to the most recently saved value. This is necessary when using the POSIX signal handling interface on some systems calling longjmp out of the signal handler to get to the top level on an interrupt doesn't restore the original signal mask. Alternatively, we could use sigsetjmp/siglongjmp, but saving and restoring the signal mask ourselves works ok and seems simpler just now. */ static sigset_t octave_signal_mask; void octave_save_signal_mask (void) { sigprocmask (0, 0, &octave_signal_mask); } void octave_restore_signal_mask (void) { sigprocmask (SIG_SETMASK, &octave_signal_mask, 0); } int octave_raise_wrapper (int signum) { return raise (signum); }