changeset 23096:b7a24a734c37

defer SIGHUP and SIGTERM actions until octave_quit is called * sighandlers.cc (user_terminate): New function. (base_interrupt_manager::do_user_terminate): New pure virtual. (w32_interrupt_manager::do_user_terminate): New function. (posix_interrupt_manager::do_user_terminate): New function. (interrupt_manager::user_terminate): New function. (my_friendly_exit): Simplify. (signal_handler): Also handle SIGHUP and SIGTERM. (sigchld_handler, sig_hup_handler, sig_term_handler): Delete. (user_terminate): New function. (int sig_number) (sigwinch_handler): Delete commented function. (sigterm_handler): New function. (install_signal_handlers): Use generic_sig_handler for SIGCHLD. Use sigterm_handler for SIGHUP and SIGTERM. Delete commented code for setting SIGWINCH.
author John W. Eaton <jwe@octave.org>
date Thu, 26 Jan 2017 17:14:58 -0500
parents 5a8979c8d0c3
children 0c5f04b9dca1
files libinterp/corefcn/sighandlers.cc
diffstat 1 files changed, 80 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/sighandlers.cc	Thu Jan 26 17:06:39 2017 -0500
+++ b/libinterp/corefcn/sighandlers.cc	Thu Jan 26 17:14:58 2017 -0500
@@ -80,7 +80,8 @@
   // List of signals we have caught since last call to octave::signal_handler.
   static bool *signals_caught = 0;
 
-  // Forward declaration.
+  // Forward declarations.
+  static void user_terminate (int sig_number);
   static void user_abort (const char *sig_name, int sig_number);
 
   class
@@ -100,6 +101,8 @@
 
     virtual void do_jump_to_enclosing_context (void) = 0;
 
+    virtual void do_user_terminate (int sig_number) = 0;
+
     virtual void do_user_abort (const char *sig_name, int sig_number) = 0;
 
     virtual void do_raise_sigint (void) = 0;
@@ -165,6 +168,20 @@
         }
     }
 
+    void do_user_terminate (int sig_number)
+    {
+      bool is_interrupt_thread = (GetCurrentThreadId () == thread_id);
+
+      if (is_interrupt_thread)
+        octave::user_terminate (sig_number);
+      else
+        {
+          SuspendThread (thread);
+          octave::user_terminate (sig_number);
+          ResumeThread (thread);
+        }
+    }
+
     void do_user_abort (const char *sig_name, int sig_number)
     {
       bool is_interrupt_thread = (GetCurrentThreadId () == thread_id);
@@ -227,6 +244,11 @@
       ::octave_jump_to_enclosing_context ();
     }
 
+    void do_user_terminate (int sig_number)
+    {
+      octave::user_terminate (sig_number);
+    }
+
     void do_user_abort (const char *sig_name, int sig_number)
     {
       octave::user_abort (sig_name, sig_number);
@@ -253,6 +275,12 @@
         instance->do_jump_to_enclosing_context ();
     }
 
+    static void user_terminate (int sig_number)
+    {
+      if (instance_ok ())
+        instance->do_user_terminate (sig_number);
+    }
+
     static void user_abort (const char *sig_name, int sig_number)
     {
       if (instance_ok ())
@@ -309,6 +337,21 @@
 
   base_interrupt_manager *interrupt_manager::instance = 0;
 
+  static void
+  my_friendly_exit (const char *sig_name, int sig_number,
+                    bool save_vars = true)
+  {
+    std::cerr << "fatal: caught signal " << sig_name
+              << " -- stopping myself..." << std::endl;
+
+    if (save_vars)
+      dump_octave_core ();
+
+    sysdep_cleanup ();
+
+    throw octave::exit_exception (1);
+  }
+
   // Called from octave_quit () to actually do something about the signals
   // we have caught.
 
@@ -320,10 +363,14 @@
 
     static int sigchld;
     static int sigfpe;
+    static int sighup;
+    static int sigterm;
     static int sigpipe;
 
     static const bool have_sigchld = octave_get_sig_number ("SIGCHLD", &sigchld);
     static const bool have_sigfpe = octave_get_sig_number ("SIGFPE", &sigfpe);
+    static const bool have_sighup = octave_get_sig_number ("SIGHUP", &sighup);
+    static const bool have_sigterm = octave_get_sig_number ("SIGTERM", &sigterm);
     static const bool have_sigpipe = octave_get_sig_number ("SIGPIPE", &sigpipe);
 
     for (int i = 0; i < octave_num_signals (); i++)
@@ -349,54 +396,16 @@
               }
             else if (have_sigfpe && i == sigfpe)
               std::cerr << "warning: floating point exception" << std::endl;
+            else if (have_sighup && i == sighup)
+              my_friendly_exit ("SIGHUP", sighup, Vsighup_dumps_octave_core);
+            else if (have_sigterm && i == sigterm)
+              my_friendly_exit ("SIGTERM", sigterm, Vsigterm_dumps_octave_core);
             else if (have_sigpipe && i == sigpipe)
               std::cerr << "warning: broken pipe" << std::endl;
           }
       }
   }
 
-  static void
-  my_friendly_exit (const char *sig_name, int sig_number,
-                    bool save_vars = true)
-  {
-    static bool been_there_done_that = false;
-
-    if (been_there_done_that)
-      {
-        set_signal_handler ("SIGABRT", SIG_DFL);
-
-        std::cerr << "panic: attempted clean up failed -- aborting..."
-                  << std::endl;
-
-        sysdep_cleanup ();
-
-        abort ();
-      }
-    else
-      {
-        been_there_done_that = true;
-
-        std::cerr << "panic: " << sig_name << " -- stopping myself..."
-                  << std::endl;
-
-        if (save_vars)
-          dump_octave_core ();
-
-        if (sig_number < 0)
-          {
-            sysdep_cleanup ();
-
-            exit (1);
-          }
-        else
-          {
-            set_signal_handler (sig_number, SIG_DFL);
-
-            octave_raise_wrapper (sig_number);
-          }
-      }
-  }
-
   sig_handler *
   set_signal_handler (int sig, sig_handler *handler, bool restart_syscalls)
   {
@@ -414,14 +423,6 @@
   static void
   generic_sig_handler (int sig)
   {
-    my_friendly_exit (octave_strsignal_wrapper (sig), sig);
-  }
-
-  // Handle SIGCHLD.
-
-  static void
-  sigchld_handler (int sig)
-  {
     octave_signal_caught = 1;
 
     signals_caught[sig] = true;
@@ -442,33 +443,28 @@
   }
 #endif
 
-  static void
-  sig_hup_handler (int /* sig */)
-  {
-    if (Vsighup_dumps_octave_core)
-      dump_octave_core ();
-
-    clean_up_and_exit (0);
-  }
+  // Handle SIGHUP and SIGTERM.
 
   static void
-  sig_term_handler (int /* sig */)
+  user_terminate (int sig_number)
   {
-    if (Vsigterm_dumps_octave_core)
-      dump_octave_core ();
+    if (! octave_initialized)
+      exit (1);
+
+    octave_signal_caught = 1;
+
+    signals_caught[sig_number] = true;
 
-    clean_up_and_exit (0);
+    if (octave_interrupt_immediately)
+      {
+        // Try to get to a place where it is safe to throw an
+        // exception.
+
+        interrupt_manager::jump_to_enclosing_context ();
+      }
   }
 
-#if 0
-  static void
-  sigwinch_handler (int /* sig */)
-  {
-    command_editor::resize_terminal ();
-  }
-#endif
-
-  // Handle SIGINT by restarting the parser (see octave.cc).
+  // 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
@@ -506,6 +502,9 @@
             if (octave_interrupt_state == 0)
               octave_interrupt_state = 1;
 
+            // Try to get to a place where it is safe to throw an
+            // exception.
+
             interrupt_manager::jump_to_enclosing_context ();
           }
         else
@@ -532,6 +531,12 @@
   }
 
   static void
+  sigterm_handler (int sig)
+  {
+    interrupt_manager::user_terminate (sig);
+  }
+
+  static void
   sigint_handler (int sig)
   {
     interrupt_manager::user_abort (octave_strsignal_wrapper (sig), sig);
@@ -609,7 +614,7 @@
     set_signal_handler ("SIGABRT", generic_sig_handler);
     set_signal_handler ("SIGALRM", generic_sig_handler);
     set_signal_handler ("SIGBUS", generic_sig_handler);
-    set_signal_handler ("SIGCHLD", sigchld_handler);
+    set_signal_handler ("SIGCHLD", generic_sig_handler);
 
     // SIGCLD
     // SIGCONT
@@ -622,7 +627,7 @@
     set_signal_handler ("SIGFPE", generic_sig_handler);
 #endif
 
-    set_signal_handler ("SIGHUP", sig_hup_handler);
+    set_signal_handler ("SIGHUP", sigterm_handler);
     set_signal_handler ("SIGILL", generic_sig_handler);
 
     // SIGINFO
@@ -642,7 +647,7 @@
     // SIGSTOP
 
     set_signal_handler ("SIGSYS", generic_sig_handler);
-    set_signal_handler ("SIGTERM", sig_term_handler);
+    set_signal_handler ("SIGTERM", sigterm_handler);
     set_signal_handler ("SIGTRAP", generic_sig_handler);
 
     // SIGTSTP