changeset 25284:78fb24bdd8bb stable

unblock async signals before executing subprocess (bug #53635) * sighandlers.cc (sigint_handler): Delete. (generic_sig_handler): Handle sigint and sigbreak here. (catch_interrupts): Use generic_sig_handler instead of sigint_handler. (F__show_signal_mask__): New function. * signal-wrappers.h, signal-wrappers.c (octave_alloc_signal_mask, octave_free_signal_mask, octave_get_signal_mask, octave_set_signal_mask): New functions. * toplev.cc (get_signal_mask, restore_signal_mask): New static functions. (Fsystem): Save signal mask. Unblock async signals before executing subprocess. Use unwind_protect frame to restore previous mask.
author John W. Eaton <jwe@octave.org>
date Thu, 19 Apr 2018 01:58:44 -0400
parents 35115cc6183b
children 9b059a36a1ae 44c0aca121cc
files libinterp/corefcn/sighandlers.cc libinterp/corefcn/toplev.cc liboctave/wrappers/signal-wrappers.c liboctave/wrappers/signal-wrappers.h
diffstat 4 files changed, 74 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/sighandlers.cc	Wed Apr 18 15:18:47 2018 -0400
+++ b/libinterp/corefcn/sighandlers.cc	Thu Apr 19 01:58:44 2018 -0400
@@ -243,7 +243,7 @@
                         << std::endl;
             else if ((have_sigint && sig == sigint)
                      || (have_sigbreak && sig == sigbreak))
-              /* handled separately; do nothing */;
+              ; // Handled separately; do nothing.
             else
               std::cerr << "warning: ignoring unexpected signal: "
                         << octave_strsignal_wrapper (sig)
@@ -287,7 +287,16 @@
 
     if ((have_sigint && sig == sigint)
         || (have_sigbreak && sig == sigbreak))
-      octave_interrupt_state++;
+      {
+        if (! octave_initialized)
+          exit (1);
+
+        if (can_interrupt)
+          {
+            octave_signal_caught = 1;
+            octave_interrupt_state++;
+          }
+      }
   }
 
   static void
@@ -310,32 +319,13 @@
     std::cerr << "warning: floating point exception" << std::endl;
   }
 
-  // Handle SIGINT.
-  //
-  // This also has to work for SIGBREAK (on systems that have it), so we
-  // use the value of sig, instead of just assuming that it is called
-  // for SIGINT only.
-
-  static void
-  sigint_handler (int)
-  {
-    if (! octave_initialized)
-      exit (1);
-
-    if (can_interrupt)
-      {
-        octave_signal_caught = 1;
-        octave_interrupt_state++;
-      }
-  }
-
   interrupt_handler
   catch_interrupts (void)
   {
     interrupt_handler retval;
 
-    retval.int_handler = set_signal_handler ("SIGINT", sigint_handler);
-    retval.brk_handler = set_signal_handler ("SIGBREAK", sigint_handler);
+    retval.int_handler = set_signal_handler ("SIGINT", generic_sig_handler);
+    retval.brk_handler = set_signal_handler ("SIGBREAK", generic_sig_handler);
 
     return retval;
   }
--- a/libinterp/corefcn/toplev.cc	Wed Apr 18 15:18:47 2018 -0400
+++ b/libinterp/corefcn/toplev.cc	Thu Apr 19 01:58:44 2018 -0400
@@ -42,6 +42,7 @@
 #include "oct-fftw.h"
 #include "oct-locbuf.h"
 #include "oct-syscalls.h"
+#include "signal-wrappers.h"
 #include "str-vec.h"
 #include "wait-for-input.h"
 
@@ -149,6 +150,28 @@
   return retval;
 }
 
+// Combine alloc+get in one action.
+
+static void *
+get_signal_mask (void)
+{
+  void *mask = octave_alloc_signal_mask ();
+
+  octave_get_signal_mask (mask);
+
+  return mask;
+}
+
+// Combine set+free in one action.
+
+static void
+restore_signal_mask (void *mask)
+{
+  octave_set_signal_mask (mask);
+
+  octave_free_signal_mask (mask);
+}
+
 enum system_exec_type { et_sync, et_async };
 
 DEFUN (system, args, nargout,
@@ -232,9 +255,6 @@
 
   octave_value_list retval;
 
-  // FIXME: Is this unwind_protect frame needed anymore (12/16/15)?
-  octave::unwind_protect frame;
-
   bool return_output = (nargin == 1 && nargout > 1);
 
   if (nargin > 1)
@@ -260,6 +280,12 @@
     cmd_str = '"' + cmd_str + '"';
 #endif
 
+  octave::unwind_protect frame;
+
+  frame.add_fcn (restore_signal_mask, get_signal_mask ());
+
+  octave_unblock_async_signals ();
+
   if (type == et_async)
     retval(0) = octave_async_system_wrapper (cmd_str.c_str ());
   else if (return_output)
--- a/liboctave/wrappers/signal-wrappers.c	Wed Apr 18 15:18:47 2018 -0400
+++ b/liboctave/wrappers/signal-wrappers.c	Thu Apr 19 01:58:44 2018 -0400
@@ -546,6 +546,30 @@
   sigprocmask (SIG_SETMASK, &octave_signal_mask, 0);
 }
 
+void *
+octave_alloc_signal_mask (void)
+{
+  return malloc (sizeof (sigset_t));
+}
+
+void
+octave_free_signal_mask (void *mask)
+{
+  free (mask);
+}
+
+void
+octave_get_signal_mask (void *mask)
+{
+  sigprocmask (0, 0, mask);
+}
+
+void
+octave_set_signal_mask (void *mask)
+{
+  sigprocmask (SIG_SETMASK, (sigset_t *) mask, 0);
+}
+
 #if ! defined (__WIN32__)
 static const sigset_t *
 octave_async_signals (void)
--- a/liboctave/wrappers/signal-wrappers.h	Wed Apr 18 15:18:47 2018 -0400
+++ b/liboctave/wrappers/signal-wrappers.h	Thu Apr 19 01:58:44 2018 -0400
@@ -76,6 +76,14 @@
 
 extern void octave_restore_signal_mask (void);
 
+extern void * octave_alloc_signal_mask (void);
+
+extern void octave_free_signal_mask (void *mask);
+
+extern void octave_get_signal_mask (void *mask);
+
+extern void octave_set_signal_mask (void *mask);
+
 extern void octave_block_async_signals (void);
 
 extern void octave_unblock_async_signals (void);