# HG changeset patch # User jwe # Date 832160808 0 # Node ID 859030f15706c4bbe3b00e0fe513d0b7d454cda7 # Parent 4be9ccca137bcab2c7a3290070e3da4058bff32c [project @ 1996-05-15 11:46:43 by jwe] diff -r 4be9ccca137b -r 859030f15706 src/pager.cc --- 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); + } } } diff -r 4be9ccca137b -r 859030f15706 src/pager.h --- 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 diff -r 4be9ccca137b -r 859030f15706 src/pt-plot.cc --- 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; diff -r 4be9ccca137b -r 859030f15706 src/sighandlers.cc --- 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++ *** diff -r 4be9ccca137b -r 859030f15706 src/sighandlers.h --- 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 + +#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 list; + + int curr_len; + + static octave_child_list *instance; + + void do_insert (pid_t pid, octave_child::dead_child_handler f); +}; + #endif /*