diff libinterp/interpfcn/toplev.cc @ 16485:8b783661e03f

improve exit sequence for GUI * octave-link.h, octave-link.cc (octave_link::accepting_events): Delete variable and all uses. (octave_link::link_enabled): New data member. (octave_link::octave_link): Don't set octave_exit. Initialize link_enabled. (octave_link::do_exit): Delete definition. Now pure virtual. Return bool. (octave_link::exit): Call instance->do_exit. (octave_link::enabled): New function. (ocave_link::process_events): New arg, disable. Optionally disable event processing. Use octave_link::enabled instead of instance_ok everywhere except for octave_link::exit. (octave_link::cleanup_instance): Delete. * octave-qt-link.h, octave-qt-link.cc (octave_qt_link::octave_qt_link): Accept thread as argument. Don't connect main_thread::finished signal. (octave_qt_link::~octave_qt_link): Don't delete main_thread. (octave_qt_link::do_exit): Emit exit_signal and return true. (octave_qt_link::exit_signal: New signal. (octave_qt_link::void octave_thread_finished_signal): Delete. * main-window.h, main-window.cc (main_window::_octave_main_thread): New member variable. (main_window::main_window): Initialize _octave_main_thread and _octave_qt_link to 0. (main_window::~main_window): Don't call octave_link::connect_link. Delete _octave_main_thread. (main_window::exit): Accept exit status as argument and call QApplication::exit instead of quit. (main_window::construct): Don't connect qApp::aboutToQuit to main_window::prepare_to_exit. (main_window::construct_octave_qt_link): Create _octave_main_thread and pass to _octave_qt_link. Don't connect _octave_qt_link::octave_thread_finished to main_window::exit. Connect _octave_qt_link::exit_signal to main_window::exit. * toplev.h, toplev.cc (main_loop): If quitting_gracefully, just return exit status instead of calling clean_up_and_exit. (do_octave_atexit): Now static. Call octave_link::process_events with disable arg set to true. (octave_atexit_functions): Now static. (clean_up_and_exit): New argument, safe_to_return. Call octave_link::exit and possibly return or wait for octave_link::exit to terminate the process. * octave.cc (octave_execute_interpreter): Don't alter return value from main_loop. Pass safe_to_return = true to clean_up_and_exit. Return retval instead of 0. (octave_initialize_interpreter): Don't call atexit.
author John W. Eaton <jwe@octave.org>
date Tue, 09 Apr 2013 23:08:24 -0400
parents fb27f1e08297
children
line wrap: on
line diff
--- a/libinterp/interpfcn/toplev.cc	Tue Apr 09 23:08:21 2013 -0400
+++ b/libinterp/interpfcn/toplev.cc	Tue Apr 09 23:08:24 2013 -0400
@@ -57,6 +57,7 @@
 #include "graphics.h"
 #include "input.h"
 #include "lex.h"
+#include "octave-link.h"
 #include "oct-conf.h"
 #include "oct-conf-features.h"
 #include "oct-hist.h"
@@ -614,10 +615,7 @@
           recover_from_exception ();
           octave_stdout << "\n";
           if (quitting_gracefully)
-            {
-              clean_up_and_exit (exit_status);
-              break; // If user has overriden the exit func.
-            }
+            return exit_status;
         }
       catch (octave_execution_exception)
         {
@@ -641,13 +639,120 @@
 
 // Fix up things before exiting.
 
+static std::list<std::string> octave_atexit_functions;
+
+static void
+do_octave_atexit (void)
+{
+  static bool deja_vu = false;
+
+  OCTAVE_SAFE_CALL (remove_input_event_hook_functions, ());
+
+  while (! octave_atexit_functions.empty ())
+    {
+      std::string fcn = octave_atexit_functions.front ();
+
+      octave_atexit_functions.pop_front ();
+
+      OCTAVE_SAFE_CALL (reset_error_handler, ());
+
+      OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0));
+
+      OCTAVE_SAFE_CALL (flush_octave_stdout, ());
+    }
+
+  if (! deja_vu)
+    {
+      deja_vu = true;
+
+      // Process pending events and disasble octave_link event
+      // processing with this call.
+
+      octave_link::process_events (true);
+
+      // Do this explicitly so that destructors for mex file objects
+      // are called, so that functions registered with mexAtExit are
+      // called.
+      OCTAVE_SAFE_CALL (clear_mex_functions, ());
+
+      OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ());
+
+      // FIXME -- is this needed?  Can it cause any trouble?
+      OCTAVE_SAFE_CALL (raw_mode, (0));
+
+      OCTAVE_SAFE_CALL (octave_history_write_timestamp, ());
+
+      if (! command_history::ignoring_entries ())
+        OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ());
+
+      OCTAVE_SAFE_CALL (gh_manager::close_all_figures, ());
+
+      OCTAVE_SAFE_CALL (gtk_manager::unload_all_toolkits, ());
+
+      OCTAVE_SAFE_CALL (close_files, ());
+
+      OCTAVE_SAFE_CALL (cleanup_tmp_files, ());
+
+      OCTAVE_SAFE_CALL (symbol_table::cleanup, ());
+
+      OCTAVE_SAFE_CALL (sysdep_cleanup, ());
+
+      OCTAVE_SAFE_CALL (flush_octave_stdout, ());
+
+      if (! quitting_gracefully && (interactive || forced_interactive))
+        {
+          octave_stdout << "\n";
+
+          // Yes, we want this to be separate from the call to
+          // flush_octave_stdout above.
+
+          OCTAVE_SAFE_CALL (flush_octave_stdout, ());
+        }
+
+      // Don't call singleton_cleanup_list::cleanup until we have the
+      // problems with registering/unregistering types worked out.  For
+      // example, uncomment the following line, then use the make_int
+      // function from the examples directory to create an integer
+      // object and then exit Octave.  Octave should crash with a
+      // segfault when cleaning up the typinfo singleton.  We need some
+      // way to force new octave_value_X types that are created in
+      // .oct files to be unregistered when the .oct file shared library
+      // is unloaded.
+      //
+      // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ());
+
+      OCTAVE_SAFE_CALL (octave_chunk_buffer::clear, ());
+    }
+}
+
 void
-clean_up_and_exit (int retval)
+clean_up_and_exit (int retval, bool safe_to_return)
 {
   do_octave_atexit ();
 
-  if (octave_exit)
-    (*octave_exit) (retval == EOF ? 0 : retval);
+  if (octave_link::exit (retval))
+    {
+      if (safe_to_return)
+        return;
+      else
+        {
+          // What should we do here?  We might be called from some
+          // location other than the end of octave_execute_interpreter,
+          // so it might not be safe to return.
+
+          // We have nothing else to do at this point, and the
+          // octave_link::exit function is supposed to take care of
+          // exiting for us.  Assume that job won't take more than a
+          // day...
+
+          gnulib::sleep (86400);
+        }
+    }
+  else
+    {
+      if (octave_exit)
+        (*octave_exit) (retval == EOF ? 0 : retval);
+    }
 }
 
 DEFUN (quit, args, ,
@@ -992,89 +1097,6 @@
 %!error system (1, 2, 3)
 */
 
-// FIXME -- this should really be static, but that causes
-// problems on some systems.
-std::list<std::string> octave_atexit_functions;
-
-void
-do_octave_atexit (void)
-{
-  static bool deja_vu = false;
-
-  OCTAVE_SAFE_CALL (remove_input_event_hook_functions, ());
-
-  while (! octave_atexit_functions.empty ())
-    {
-      std::string fcn = octave_atexit_functions.front ();
-
-      octave_atexit_functions.pop_front ();
-
-      OCTAVE_SAFE_CALL (reset_error_handler, ());
-
-      OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0));
-
-      OCTAVE_SAFE_CALL (flush_octave_stdout, ());
-    }
-
-  if (! deja_vu)
-    {
-      deja_vu = true;
-
-      // Do this explicitly so that destructors for mex file objects
-      // are called, so that functions registered with mexAtExit are
-      // called.
-      OCTAVE_SAFE_CALL (clear_mex_functions, ());
-
-      OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ());
-
-      // FIXME -- is this needed?  Can it cause any trouble?
-      OCTAVE_SAFE_CALL (raw_mode, (0));
-
-      OCTAVE_SAFE_CALL (octave_history_write_timestamp, ());
-
-      if (! command_history::ignoring_entries ())
-        OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ());
-
-      OCTAVE_SAFE_CALL (gh_manager::close_all_figures, ());
-
-      OCTAVE_SAFE_CALL (gtk_manager::unload_all_toolkits, ());
-
-      OCTAVE_SAFE_CALL (close_files, ());
-
-      OCTAVE_SAFE_CALL (cleanup_tmp_files, ());
-
-      OCTAVE_SAFE_CALL (symbol_table::cleanup, ());
-
-      OCTAVE_SAFE_CALL (sysdep_cleanup, ());
-
-      OCTAVE_SAFE_CALL (flush_octave_stdout, ());
-
-      if (! quitting_gracefully && (interactive || forced_interactive))
-        {
-          octave_stdout << "\n";
-
-          // Yes, we want this to be separate from the call to
-          // flush_octave_stdout above.
-
-          OCTAVE_SAFE_CALL (flush_octave_stdout, ());
-        }
-
-      // Don't call singleton_cleanup_list::cleanup until we have the
-      // problems with registering/unregistering types worked out.  For
-      // example, uncomment the following line, then use the make_int
-      // function from the examples directory to create an integer
-      // object and then exit Octave.  Octave should crash with a
-      // segfault when cleaning up the typinfo singleton.  We need some
-      // way to force new octave_value_X types that are created in
-      // .oct files to be unregistered when the .oct file shared library
-      // is unloaded.
-      //
-      // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ());
-
-      OCTAVE_SAFE_CALL (octave_chunk_buffer::clear, ());
-    }
-}
-
 void
 octave_add_atexit_function (const std::string& fname)
 {