changeset 23092:0fed4c678795

additional restructuring of startup and shutdown * main-window.h, main-window.cc (main_window::~main_window): Don't delete _octave_qt_link here. (main_window::exit_app): Delete. (main_window::construct_octave_qt_link): Delete connection from octave_qt_link::exit_app_signal to main_window::exit_app slot. Call octave_link::connect_link immediately after constructing new octave_qt_link_object. * octave-interpreter.h, octave-interpreter.cc (octave_interpreter::m_exit_status): Delete unused data member. (octave_interpreter::execute): Call qApp->exit here. * octave-link.h (octave_link::do_exit): Delete. (octave_link::exit): Delete. (octave_link::disconnect_link, octave_link::enable, octave_link::disable, octave_link::do_enable, octave_link::do_disable): New functions. (octave_link::process_events): Call do_disable instead of accessing link_enabled directly. (octave_link::confirm_shutdown): Check enabled, not instance_ok. * octave-qt-link.h, octave-qt-link.cc (octave_qt_link::do_exit): Delete. (octave_qt_link::exit_app_signal): Delete. * interpreter.h, interpreter.cc (interpreter::execute_internal): New function. Perform interpreter::execute actions here. Simply handle If not in persist mode, simply return status from execute_eval_option_code and execute_command_line_file. Simply return status from main_loop. Don't set m_quitting_gracefully here. (interpreter::execute): Wrap interpreter::execute_internal in try-catch block. If exit_exception is caught, process octave_link events and disconnect link here. Call cleanup here, not from destructor. (interpreter::m_quitting_gracefully): Delete data member and all uses. (safe_source_file, execute_pkg_add): Don't catch index_exception. Dopn't display message for execution_exception. (initialize_load_path, execute_startup_files): Return status from safe_source_file. Don't fail, but preserve any non-zero status. (interpreter::execute_eval_option_code): Don't catch exit_exception here. (interpreter::main_loop): Don't print extra newline when interactive main loop is done. (interpreter::cleanup): Don't call raw_mode.
author John W. Eaton <jwe@octave.org>
date Thu, 26 Jan 2017 08:26:46 -0500
parents bc601e5137c5
children 8aba6d170887
files etc/HACKING libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-interpreter.cc libgui/src/octave-interpreter.h libgui/src/octave-qt-link.cc libgui/src/octave-qt-link.h libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/octave-link.h
diffstat 10 files changed, 129 insertions(+), 148 deletions(-) [+]
line wrap: on
line diff
--- a/etc/HACKING	Wed Jan 25 16:11:51 2017 -0800
+++ b/etc/HACKING	Thu Jan 26 08:26:46 2017 -0500
@@ -336,7 +336,7 @@
 John W. Eaton
 jwe@octave.org
 
-Last updated: Tue, 29 Oct 2013 11:42:47 PDT
+Last updated: Thu, 26 Jan 2017 08:29:19 EST
 
 
 ################################################################################
--- a/libgui/src/main-window.cc	Wed Jan 25 16:11:51 2017 -0800
+++ b/libgui/src/main-window.cc	Thu Jan 26 08:26:46 2017 -0500
@@ -162,7 +162,6 @@
       delete community_news_window;
       community_news_window = 0;
     }
-  delete _octave_qt_link;
 }
 
 // catch focus changes and determine the active dock widget
@@ -831,12 +830,6 @@
 }
 
 void
-main_window::exit_app (int status)
-{
-  qApp->exit (status);
-}
-
-void
 main_window::reset_windows (void)
 {
   QSettings *settings = resource_manager::get_default_settings ();
@@ -1515,8 +1508,7 @@
 {
   _octave_qt_link = new octave_qt_link (this, m_app_context);
 
-  connect (_octave_qt_link, SIGNAL (exit_app_signal (int)),
-           this, SLOT (exit_app (int)));
+  octave_link::connect_link (_octave_qt_link);
 
   connect (_octave_qt_link, SIGNAL (confirm_shutdown_signal ()),
            this, SLOT (confirm_shutdown_octave ()));
@@ -1616,8 +1608,6 @@
                _octave_qt_link, SLOT (terminal_interrupt (void)));
     }
 
-  octave_link::connect_link (_octave_qt_link);
-
   // Defer initializing and executing the interpreter until after the main
   // window and QApplication are running to prevent race conditions
   QTimer::singleShot (0, this, SLOT (execute_octave_interpreter ()));
--- a/libgui/src/main-window.h	Wed Jan 25 16:11:51 2017 -0800
+++ b/libgui/src/main-window.h	Thu Jan 26 08:26:46 2017 -0500
@@ -142,7 +142,6 @@
   void notice_settings (const QSettings *settings);
   void confirm_shutdown_octave (void);
   void prepare_to_exit (void);
-  void exit_app (int status);
   void reset_windows (void);
 
   void change_directory (const QString& dir);
--- a/libgui/src/octave-interpreter.cc	Wed Jan 25 16:11:51 2017 -0800
+++ b/libgui/src/octave-interpreter.cc	Thu Jan 26 08:26:46 2017 -0500
@@ -25,13 +25,14 @@
 #  include "config.h"
 #endif
 
+#include <QApplication>
+
 #include "octave.h"
 
 #include "octave-interpreter.h"
 
 octave_interpreter::octave_interpreter (octave::application *app_context)
-  : QObject (), thread_manager (), m_app_context (app_context),
-    m_exit_status (0)
+  : QObject (), thread_manager (), m_app_context (app_context)
 { }
 
 void
@@ -47,7 +48,9 @@
 
   emit octave_ready_signal ();
 
-  m_exit_status = m_app_context->execute_interpreter ();
+  int exit_status = m_app_context->execute_interpreter ();
+
+  qApp->exit (exit_status);
 }
 
 void
--- a/libgui/src/octave-interpreter.h	Wed Jan 25 16:11:51 2017 -0800
+++ b/libgui/src/octave-interpreter.h	Thu Jan 26 08:26:46 2017 -0500
@@ -59,8 +59,6 @@
   octave_thread_manager thread_manager;
 
   octave::application *m_app_context;
-
-  int m_exit_status;
 };
 
 #endif
--- a/libgui/src/octave-qt-link.cc	Wed Jan 25 16:11:51 2017 -0800
+++ b/libgui/src/octave-qt-link.cc	Thu Jan 26 08:26:46 2017 -0500
@@ -96,16 +96,6 @@
 }
 
 bool
-octave_qt_link::do_exit (int status)
-{
-  emit exit_app_signal (status);
-
-  // Could wait for a while and then timeout, but for now just
-  // assume the GUI application exit will be without problems.
-  return true;
-}
-
-bool
 octave_qt_link::do_copy_image_to_clipboard (const std::string& file)
 {
   emit copy_image_to_clipboard_signal (QString::fromStdString (file), true);
--- a/libgui/src/octave-qt-link.h	Wed Jan 25 16:11:51 2017 -0800
+++ b/libgui/src/octave-qt-link.h	Thu Jan 26 08:26:46 2017 -0500
@@ -63,7 +63,6 @@
   void execute_interpreter (void);
 
   bool do_confirm_shutdown (void);
-  bool do_exit (int status);
 
   bool do_copy_image_to_clipboard (const std::string& file);
 
@@ -205,7 +204,6 @@
   void show_doc_signal (const QString &file);
 
   void confirm_shutdown_signal (void);
-  void exit_app_signal (int status);
 
 public slots:
 
--- a/libinterp/corefcn/interpreter.cc	Wed Jan 25 16:11:51 2017 -0800
+++ b/libinterp/corefcn/interpreter.cc	Thu Jan 26 08:26:46 2017 -0500
@@ -362,15 +362,6 @@
     {
       octave::source_file (file_name, context, verbose, require_file, warn_for);
     }
-  catch (const octave::index_exception& e)
-    {
-      recover_from_exception ();
-
-      std::cerr << "error: index exception in " << file_name << ": "
-                << e.message () << std::endl;
-
-      return 1;
-    }
   catch (const octave::interrupt_exception&)
     {
       recover_from_exception ();
@@ -381,8 +372,6 @@
     {
       recover_from_exception ();
 
-      std::cerr << "error: execution exception in " << file_name << std::endl;
-
       return 1;
     }
 
@@ -398,13 +387,6 @@
     {
       load_path::execute_pkg_add (dir);
     }
-  catch (const octave::index_exception& e)
-    {
-      recover_from_exception ();
-
-      std::cerr << "error: index exception in " << file_name << ": "
-                << e.message () << std::endl;
-    }
   catch (const octave::interrupt_exception&)
     {
       recover_from_exception ();
@@ -412,8 +394,6 @@
   catch (const octave::execution_exception&)
     {
       recover_from_exception ();
-
-      std::cerr << "error: execution exception in " << file_name << std::endl;
     }
 }
 
@@ -437,9 +417,11 @@
   load_path::initialize (set_initial_path);
 }
 
-// Initialize by reading startup files.
+// Initialize by reading startup files.  Return non-zero if an exception
+// occurs when reading any of them, but don't exit early because of an
+// exception.
 
-static void
+static int
 execute_startup_files (bool read_site_files, bool read_init_files,
                        bool verbose_flag, bool inhibit_startup_message)
 {
@@ -451,6 +433,8 @@
 
   bool require_file = false;
 
+  int exit_status = 0;
+
   if (read_site_files)
     {
       // Execute commands from the site-wide configuration file.
@@ -458,10 +442,17 @@
       // (if it exists), then from the file
       // $(prefix)/share/octave/$(version)/m/octaverc (if it exists).
 
-      safe_source_file (Vlocal_site_defaults_file, context, verbose,
-                        require_file);
+      int status = safe_source_file (Vlocal_site_defaults_file, context,
+                                     verbose, require_file);
+
+      if (status)
+        exit_status = status;
 
-      safe_source_file (Vsite_defaults_file, context, verbose, require_file);
+      status = safe_source_file (Vsite_defaults_file, context, verbose,
+                                 require_file);
+
+      if (status)
+        exit_status = status;
     }
 
   if (read_init_files)
@@ -485,7 +476,11 @@
 
       if (! home_rc.empty ())
         {
-          safe_source_file (home_rc, context, verbose, require_file);
+          int status = safe_source_file (home_rc, context, verbose,
+                                         require_file);
+
+          if (status)
+            exit_status = status;
 
           // Names alone are not enough.
 
@@ -507,9 +502,15 @@
           if (local_rc.empty ())
             local_rc = octave::sys::env::make_absolute (initfile);
 
-          safe_source_file (local_rc, context, verbose, require_file);
+          int status = safe_source_file (local_rc, context, verbose,
+                                         require_file);
+
+          if (status)
+            exit_status = status;
         }
     }
+
+  return exit_status;
 }
 
 namespace octave
@@ -518,8 +519,7 @@
 
   interpreter::interpreter (application *app_context, bool embedded)
     : m_app_context (app_context), m_evaluator (new tree_evaluator (this)),
-      m_embedded (embedded), m_interactive (false),
-      m_quitting_gracefully (false)
+      m_embedded (embedded), m_interactive (false)
   {
     current_evaluator = m_evaluator;
 
@@ -639,8 +639,6 @@
 
   interpreter::~interpreter (void)
   {
-    cleanup ();
-
     current_evaluator = 0;
 
     delete m_evaluator;
@@ -648,6 +646,24 @@
 
   int interpreter::execute (void)
   {
+    int exit_status = 0;
+
+    try
+      {
+        exit_status = execute_internal ();
+      }
+    catch (const octave::exit_exception& ex)
+      {
+        exit_status = ex.exit_status ();
+      }
+
+    cleanup ();
+
+    return exit_status;
+  }
+
+  int interpreter::execute_internal (void)
+  {
     cmdline_options options = m_app_context->options ();
 
     if (m_interactive && ! options.inhibit_startup_message ())
@@ -655,10 +671,18 @@
 
     octave_prepare_hdf5 ();
 
-    execute_startup_files (options.read_site_files (),
-                           options.read_init_files (),
-                           options.verbose_flag (),
-                           options.inhibit_startup_message ());
+    // Don't fail, but return non-zero if there is an error in a startup
+    // file.
+
+    int exit_status = 0;
+
+    int status = execute_startup_files (options.read_site_files (),
+                                        options.read_init_files (),
+                                        options.verbose_flag (),
+                                        options.inhibit_startup_message ());
+
+    if (status)
+      exit_status = status;
 
     if (m_interactive && ! options.inhibit_startup_message ()
         && reading_startup_message_printed)
@@ -669,25 +693,13 @@
 
     if (! code_to_eval.empty ())
       {
-        int exit_status = 0;
+        status = execute_eval_option_code (code_to_eval);
 
-        try
-          {
-            exit_status = execute_eval_option_code (code_to_eval);
-          }
-        catch (const octave::exit_exception& ex)
-          {
-            recover_from_exception ();
-
-            return ex.exit_status ();
-          }
+        if (status)
+          exit_status = status;
 
         if (! options.persist ())
-          {
-            m_quitting_gracefully = true;
-
-            return exit_status;
-          }
+          return exit_status;
       }
 
     // If there is an extra argument, see if it names a file to read.
@@ -698,32 +710,20 @@
         // If we are running an executable script (#! /bin/octave) then
         // we should only see the args passed to the script.
 
-        int exit_status = 0;
+        string_vector script_args = options.remaining_args ();
 
-        try
-          {
-            string_vector script_args = options.remaining_args ();
-
-            m_app_context->intern_argv (script_args);
+        m_app_context->intern_argv (script_args);
 
-            exit_status = execute_command_line_file (script_args[0]);
-          }
-        catch (const octave::exit_exception& ex)
-          {
-            recover_from_exception ();
+        status = execute_command_line_file (script_args[0]);
 
-            return ex.exit_status ();
-          }
+        if (status)
+          exit_status = status;
 
         // Restore full set of args.
         m_app_context->intern_argv (options.all_args ());
 
         if (! options.persist ())
-          {
-            m_quitting_gracefully = true;
-
-            return exit_status;
-          }
+          return exit_status;
       }
 
     // Avoid counting commands executed from startup or script files.
@@ -750,11 +750,7 @@
         return 1;
       }
 
-    int retval = main_loop ();
-
-    m_quitting_gracefully = true;
-
-    return retval;
+    return main_loop ();
   }
 
   int interpreter::execute_eval_option_code (const std::string& code)
@@ -904,16 +900,6 @@
                   break;
               }
           }
-        catch (const octave::exit_exception& ex)
-          {
-            recover_from_exception ();
-
-            // If we are connected to a gui, allow it to manage the exit
-            // process.
-            octave_link::exit (ex.exit_status ());
-
-            return ex.exit_status ();
-          }
         catch (const octave::interrupt_exception&)
           {
             recover_from_exception ();
@@ -964,9 +950,6 @@
       }
     while (retval == 0);
 
-    if (octave::application::interactive ())
-      octave_stdout << "\n";
-
     if (retval == EOF)
       retval = 0;
 
@@ -977,6 +960,12 @@
   {
     static bool deja_vu = false;
 
+    // If we are attached to a GUI, process pending events and
+    // disconnect the link.
+
+    octave_link::process_events (true);
+    octave_link::disconnect_link ();
+
     OCTAVE_SAFE_CALL (remove_input_event_hook_functions, ());
 
     while (! octave_atexit_functions.empty ())
@@ -1003,9 +992,6 @@
 
         OCTAVE_SAFE_CALL (octave::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 (! octave::command_history::ignoring_entries ())
@@ -1027,7 +1013,7 @@
 
         OCTAVE_SAFE_CALL (octave::flush_stdout, ());
 
-        if (! m_quitting_gracefully && octave::application::interactive ())
+        if (octave::application::interactive ())
           {
             octave_stdout << "\n";
 
--- a/libinterp/corefcn/interpreter.h	Wed Jan 25 16:11:51 2017 -0800
+++ b/libinterp/corefcn/interpreter.h	Thu Jan 26 08:26:46 2017 -0500
@@ -118,6 +118,8 @@
 
   private:
 
+    int execute_internal (void);
+
     int main_loop (void);
 
     void cleanup (void);
@@ -130,8 +132,6 @@
 
     // TRUE means this is an interactive interpreter (forced or not).
     bool m_interactive;
-
-    bool m_quitting_gracefully;
   };
 }
 
--- a/libinterp/corefcn/octave-link.h	Wed Jan 25 16:11:51 2017 -0800
+++ b/libinterp/corefcn/octave-link.h	Thu Jan 26 08:26:46 2017 -0500
@@ -76,7 +76,7 @@
     if (enabled ())
       {
         if (disable)
-          instance->link_enabled = false;
+          instance->do_disable ();
 
         instance->do_process_events ();
       }
@@ -92,34 +92,12 @@
   {
     bool retval = true;
 
-    if (instance_ok ())
+    if (enabled ())
       retval = instance->do_confirm_shutdown ();
 
     return retval;
   }
 
-  static bool exit (int status, bool process_events = true)
-  {
-    bool retval = false;
-
-    if (instance_ok ())
-      {
-        if (process_events)
-          {
-            // Disable additional event processing prior to processing
-            // all other pending events.
-
-            instance->link_enabled = false;
-
-            instance->do_process_events ();
-          }
-
-        retval = instance->do_exit (status);
-      }
-
-    return retval;
-  }
-
   template <typename T>
   static void post_event (T *obj, void (T::*method) (void))
   {
@@ -332,6 +310,22 @@
 
   static void connect_link (octave_link *);
 
+  static octave_link *disconnect_link (bool delete_instance = true)
+  {
+    if (delete_instance)
+      {
+        delete instance;
+        instance = 0;
+        return 0;
+      }
+    else
+      {
+        octave_link *retval = instance;
+        instance = 0;
+        return retval;
+      }
+  }
+
   static void set_default_prompts (std::string& ps1, std::string& ps2,
                                    std::string& ps4)
   {
@@ -339,6 +333,30 @@
       instance->do_set_default_prompts (ps1, ps2, ps4);
   }
 
+  static bool enable (void)
+  {
+    return instance_ok () ? instance->do_enable () : false;
+  }
+
+  static bool disable (void)
+  {
+    return instance_ok () ? instance->do_disable () : false;
+  }
+
+  bool do_enable (void)
+  {
+    bool retval = link_enabled;
+    link_enabled = true;
+    return retval;
+  }
+
+  bool do_disable (void)
+  {
+    bool retval = link_enabled;
+    link_enabled = false;
+    return retval;
+  }
+
   static bool enabled (void)
   {
     return instance_ok () ? instance->link_enabled : false;
@@ -412,7 +430,6 @@
   void do_finished_readline_hook (void) { }
 
   virtual bool do_confirm_shutdown (void) = 0;
-  virtual bool do_exit (int status) = 0;
 
   virtual bool do_copy_image_to_clipboard (const std::string& file) = 0;