changeset 2209:859030f15706

[project @ 1996-05-15 11:46:43 by jwe]
author jwe
date Wed, 15 May 1996 11:46:48 +0000
parents 4be9ccca137b
children a3e39f8efed2
files src/pager.cc src/pager.h src/pt-plot.cc src/sighandlers.cc src/sighandlers.h
diffstat 5 files changed, 202 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/pager.cc	Wed May 15 11:43:00 1996 +0000
+++ b/src/pager.cc	Wed May 15 11:46:48 1996 +0000
@@ -45,7 +45,7 @@
 #include "unwind-prot.h"
 #include "utils.h"
 
-pid_t octave_pager_pid = -1;
+static pid_t octave_pager_pid = -1;
 
 // Our actual connection to the external pager.
 static oprocstream *external_pager = 0;
@@ -93,6 +93,24 @@
 }
 
 static void
+pager_death_handler (pid_t pid, int status)
+{
+  if (pid > 0)
+    {
+      if (WIFEXITED (status) || WIFSIGNALLED (status))
+	{
+	  octave_pager_pid = -1;
+
+	  // Don't call error() here because we don't want to set
+	  // the error state.
+
+	  warning ("connection to external pager lost --");
+	  warning ("pending computations and output have been discarded");
+	}
+    }
+}
+
+static void
 do_sync (const char *msg, bool bypass_pager)
 {
   if (msg && *msg)
@@ -113,7 +131,12 @@
 		  external_pager = new oprocstream (pgr.c_str ());
 
 		  if (external_pager)
-		    octave_pager_pid = external_pager->pid ();
+		    {
+		      octave_pager_pid = external_pager->pid ();
+
+		      octave_child_list::insert (octave_pager_pid,
+						 pager_death_handler);
+		    }
 		}
 	    }
 
--- a/src/pager.h	Wed May 15 11:43:00 1996 +0000
+++ b/src/pager.h	Wed May 15 11:46:48 1996 +0000
@@ -114,8 +114,6 @@
 
 extern void flush_octave_stdout (void);
 
-extern pid_t octave_pager_pid;
-
 extern void symbols_of_pager (void);
 
 #endif
--- a/src/pt-plot.cc	Wed May 15 11:43:00 1996 +0000
+++ b/src/pt-plot.cc	Wed May 15 11:46:48 1996 +0000
@@ -58,6 +58,7 @@
 #include "pt-exp.h"
 #include "pt-plot.h"
 #include "pt-walk.h"
+#include "sighandlers.h"
 #include "sysdep.h"
 #include "utils.h"
 
@@ -117,6 +118,17 @@
 #endif
 
 static void
+plot_stream_death_handler (pid_t pid, int)
+{
+  close_plot_stream ();
+
+  warning ("connection to external plotter (pid = %d) lost --", pid);
+  warning ("please try your plot command(s) again");
+}
+
+static sig_handler *saved_sigint_handler = 0;
+
+static void
 open_plot_stream (void)
 {
   static bool initialized = false;
@@ -135,45 +147,35 @@
 
       string plot_prog = Vgnuplot_binary;
 
-      if (! plot_prog.empty ())
+      if (plot_prog.empty ())
+	plot_prog = "gnuplot";
+
+      // XXX FIXME XXX -- I'm not sure this is the right thing to do,
+      // but without it, C-c at the octave prompt will kill gnuplot...
+
+      saved_sigint_handler = octave_set_signal_handler (SIGINT, SIG_IGN);
+
+      plot_stream = new oprocstream (plot_prog.c_str ());
+
+      octave_set_signal_handler (SIGINT, saved_sigint_handler);
+
+      if (plot_stream)
 	{
-	  plot_stream = new oprocstream (plot_prog.c_str ());
-
-	  if (plot_stream && ! *plot_stream)
+	  if (! *plot_stream)
 	    {
 	      delete plot_stream;
 	      plot_stream = 0;
+
+	      error ("plot: unable to open pipe to `%s'", plot_prog.c_str ());
 	    }
-
-	  if (! plot_stream)
+	  else
 	    {
-	      warning ("plot: unable to open pipe to `%s'",
-		       plot_prog.c_str ());
-
-	      if (plot_prog == "gnuplot")
-		{
-		  warning ("having trouble finding plotting program.");
-		  warning ("trying again with `gnuplot'");
-		  goto last_chance;
-		}
+	      pid_t id = plot_stream->pid ();
+    	      octave_child_list::insert (id, plot_stream_death_handler);
 	    }
 	}
       else
-	{
-	last_chance:
-
-	  plot_stream = new oprocstream ("gnuplot");
-
-	  if (plot_stream && ! *plot_stream)
-	    {
-	      delete plot_stream;
-	      plot_stream = 0;
-	    }
-
-	  if (! plot_stream)
-	    error ("plot: unable to open pipe to `%s'",
-		   plot_prog.c_str ());
-	}
+	error ("plot: unable to open pipe to `%s'", plot_prog.c_str ());
     }
 
   if (! error_state && plot_stream && *plot_stream && ! initialized)
@@ -189,10 +191,6 @@
 static int
 send_to_plot_stream (const char *cmd)
 {
-  // From sighandlers.cc:
-
-  extern int pipe_handler_error_count;
-
   if (! (plot_stream && *plot_stream))
     {
       open_plot_stream ();
@@ -221,7 +219,6 @@
 	*plot_stream << GNUPLOT_COMMAND_REPLOT << "\n";
 
       plot_stream->flush ();
-      pipe_handler_error_count = 0;
     }
 
   return 0;
--- a/src/sighandlers.cc	Wed May 15 11:43:00 1996 +0000
+++ b/src/sighandlers.cc	Wed May 15 11:46:48 1996 +0000
@@ -133,11 +133,6 @@
 
 // Handle SIGCHLD.
 
-// XXX FIXME XXX -- this should probably be implemented by having a
-// global list of pids to check and a corresponding list of functions
-// to call if a pid is recognized.  That way, we just have to register
-// functions elsewhere and this function doesn't have to change.
-
 static RETSIGTYPE
 sigchld_handler (int /* sig */)
 {
@@ -146,22 +141,28 @@
 
   octave_set_signal_handler (SIGCHLD, sigchld_handler);
 
-  if (octave_pager_pid > 0)
+  int n = octave_child_list::length ();
+
+  for (int i = 0; i < n; i++)
     {
-      int status;
-      pid_t pid = waitpid (octave_pager_pid, &status, 0);
+      octave_child& elt = octave_child_list::elem (i);
+
+      pid_t pid = elt.pid;
 
       if (pid > 0)
 	{
-	  if (WIFEXITED (status) || WIFSIGNALLED (status))
+	  int status;
+
+	  if (waitpid (pid, &status, 0) > 0)
 	    {
-	      octave_pager_pid = -1;
+	      elt.pid = -1;
 
-	      // Don't call error() here because we don't want to set
-	      // the error state.
+	      octave_child::dead_child_handler f = elt.handler;
 
-	      warning ("connection to external pager lost --");
-	      warning ("pending computations and output have been discarded");
+	      if (f)
+		(*f) (pid, status);
+
+	      break;
 	    }
 	}
     }
@@ -441,6 +442,57 @@
   };
 #endif
 
+octave_child_list *octave_child_list::instance = 0;
+
+void
+octave_child_list::do_insert (pid_t pid, octave_child::dead_child_handler f)
+{
+  // Insert item in first open slot, increasing size of list if
+  // necessary.
+
+  bool enlarge = true;
+
+  for (int i = 0; i < curr_len; i++)
+    {
+      octave_child tmp = list.elem (i);
+
+      if (tmp.pid < 0)
+	{
+	  list.elem (i) = octave_child (pid, f);
+	  enlarge = false;
+	  break;
+	}
+    }
+
+  if (enlarge)
+    {
+      int total_len = list.length ();
+
+      if (curr_len == total_len)
+	{
+	  if (total_len == 0)
+	    list.resize (16);
+	  else
+	    list.resize (total_len * 2);
+	}
+
+      list.elem (curr_len) = octave_child (pid, f);
+      curr_len++;
+    }
+}
+
+void
+octave_child_list::insert (pid_t pid, octave_child::dead_child_handler f)
+{
+  if (! instance)
+    instance = new octave_child_list ();
+
+  if (instance)
+    instance->do_insert (pid, f);
+  else
+    panic_impossible ();
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/sighandlers.h	Wed May 15 11:43:00 1996 +0000
+++ b/src/sighandlers.h	Wed May 15 11:46:48 1996 +0000
@@ -25,6 +25,10 @@
 #if !defined (octave_sighandlers_h)
 #define octave_sighandlers_h 1
 
+#include <Array.h>
+
+#include "syswait.h"
+
 // Signal handler return type.
 #ifndef RETSIGTYPE
 #define RETSIGTYPE void
@@ -64,6 +68,81 @@
 #endif
 #endif
 
+// Maybe this should be in a separate file?
+
+class
+octave_child
+{
+public:
+
+  typedef void (*dead_child_handler) (pid_t, int);
+
+  octave_child (pid_t id = -1, dead_child_handler f = 0)
+    : pid (id), handler (f) { }
+
+  octave_child (const octave_child& oc)
+    : pid (oc.pid), handler (oc.handler) { }
+
+  octave_child& operator = (const octave_child& oc)
+    {
+      if (&oc != this)
+	{
+	  pid = oc.pid;
+	  handler = oc.handler;
+	}
+      return *this;
+    }
+
+  ~octave_child (void) { }
+
+  // The process id of this child.
+  pid_t pid;
+
+  // The function we call if this child dies.
+  dead_child_handler handler;
+};
+
+class
+octave_child_list
+{
+protected:
+
+  octave_child_list (void) : list (0), curr_len (0) { }
+
+public:
+
+  ~octave_child_list (void) { }
+
+  static void insert (pid_t pid, octave_child::dead_child_handler f);
+
+  static int length (void) { return instance ? instance->curr_len : 0; }
+
+  static octave_child& elem (int i)
+    {
+      static octave_child foo;
+
+      if (instance)
+	{
+	  int n = length ();
+
+	  if (i >= 0 && i < n)
+	    return instance->list (i);
+	}
+
+      return foo;
+    }
+
+private:
+
+  Array<octave_child> list;
+
+  int curr_len;
+
+  static octave_child_list *instance;
+
+  void do_insert (pid_t pid, octave_child::dead_child_handler f);
+};
+
 #endif
 
 /*