Mercurial > octave-nkf
diff src/sighandlers.cc @ 5142:0f9108f298ab
[project @ 2005-02-12 02:29:34 by jwe]
author | jwe |
---|---|
date | Sat, 12 Feb 2005 02:29:35 +0000 |
parents | 2c4b08ace285 |
children | 25b090e1be9f |
line wrap: on
line diff
--- a/src/sighandlers.cc Thu Feb 10 18:37:55 2005 +0000 +++ b/src/sighandlers.cc Sat Feb 12 02:29:35 2005 +0000 @@ -93,6 +93,42 @@ do { } while (0) #endif +// List of signals we have caught since last call to octave_signal_handler. +static bool octave_signals_caught[NSIG]; + +// Called from OCTAVE_QUIT to actually do something about the signals +// we have caught. + +void +octave_signal_handler (void) +{ + // The list of signals is relatively short, so we will just go + // linearly through the list. + + for (int i = 0; i < NSIG; i++) + { + if (octave_signals_caught[i]) + { + octave_signals_caught[i] = false; + + switch (i) + { + case SIGCHLD: + octave_child_list::reap (); + break; + + case SIGFPE: + std::cerr << "warning: floating point exception -- trying to return to prompt" << std::endl; + break; + + case SIGPIPE: + std::cerr << "warning: broken pipe -- some output may be lost" << std::endl; + break; + } + } + } +} + static void my_friendly_exit (const char *sig_name, int sig_number, bool save_vars = true) @@ -181,30 +217,13 @@ BLOCK_CHILD (set, oset); - int n = octave_child_list::length (); - - for (int i = 0; i < n; i++) + if (octave_child_list::wait ()) { - octave_child& elt = octave_child_list::elem (i); - - pid_t pid = elt.pid; - - if (pid > 0) - { - int status; + // The status of some child changed. - if (waitpid (pid, &status, WNOHANG) > 0) - { - elt.pid = -1; - - octave_child::dead_child_handler f = elt.handler; + octave_signal_caught = 1; - if (f) - f (pid, status); - - break; - } - } + octave_signals_caught[SIGCHLD] = true; } octave_set_interrupt_handler (saved_interrupt_handler); @@ -232,13 +251,14 @@ MAYBE_REINSTALL_SIGHANDLER (SIGFPE, sigfpe_handler); - std::cerr << "error: floating point exception -- trying to return to prompt\n"; + if (can_interrupt && octave_interrupt_state >= 0) + { + octave_signal_caught = 1; - // XXX FIXME XXX -- will setting octave_interrupt_state really help - // here? + octave_signals_caught[SIGFPE] = true; - if (can_interrupt && octave_interrupt_state >= 0) - octave_interrupt_state++; + octave_interrupt_state++; + } SIGHANDLER_RETURN (0); } @@ -341,6 +361,7 @@ if (octave_interrupt_state < 0) octave_interrupt_state = 0; + octave_signal_caught = 1; octave_interrupt_state++; if (interactive && octave_interrupt_state == 2) @@ -362,15 +383,13 @@ MAYBE_REINSTALL_SIGHANDLER (SIGPIPE, sigpipe_handler); - if (pipe_handler_error_count++ == 0) - std::cerr << "warning: broken pipe\n"; + octave_signal_caught = 1; + + octave_signals_caught[SIGPIPE] = true; // Don't loop forever on account of this. - // XXX FIXME XXX -- will setting octave_interrupt_state really help - // here? - - if (pipe_handler_error_count > 100 && octave_interrupt_state >= 0) + if (pipe_handler_error_count++ > 100 && octave_interrupt_state >= 0) octave_interrupt_state++; SIGHANDLER_RETURN (0); @@ -430,6 +449,9 @@ void install_signal_handlers (void) { + for (int i = 0; i < NSIG; i++) + octave_signals_caught[i] = false; + octave_catch_interrupts (); #ifdef SIGABRT @@ -702,13 +724,7 @@ return m; } -octave_child_list *octave_child_list::instance = 0; - -// This needs to be here for linking on AIX, at least for some -// versions of GCC, otherwise we fail with unresolved references to -// the Array<octave_child> destructor. - -octave_child_list::~octave_child_list (void) { } +octave_child_list::octave_child_list_rep *octave_child_list::instance = 0; bool octave_child_list::instance_ok (void) @@ -716,7 +732,7 @@ bool retval = true; if (! instance) - instance = new octave_child_list (); + instance = new octave_child_list_rep (); if (! instance) { @@ -729,104 +745,112 @@ } void -octave_child_list::insert (pid_t pid, octave_child::dead_child_handler f) +octave_child_list::insert (pid_t pid, octave_child::child_event_handler f) +{ + if (instance_ok ()) + instance->insert (pid, f); +} + +void +octave_child_list::reap (void) { if (instance_ok ()) - instance->do_insert (pid, f); + instance->reap (); +} + +bool +octave_child_list::wait (void) +{ + return (instance_ok ()) ? instance->wait () : false; } +class pid_equal +{ +public: + + pid_equal (pid_t v) : val (v) { } + + bool operator () (const octave_child& oc) const { return oc.pid == val; } + +private: + + pid_t val; +}; + void octave_child_list::remove (pid_t pid) { if (instance_ok ()) - instance->do_remove (pid); + instance->remove_if (pid_equal (pid)); } -int -octave_child_list::length (void) -{ - return (instance_ok ()) ? instance->do_length () : 0; -} +#define OCL_REP octave_child_list::octave_child_list_rep -octave_child& -octave_child_list::elem (int i) +void +OCL_REP::insert (pid_t pid, octave_child::child_event_handler f) { - static octave_child foo; - - return (instance_ok ()) ? instance->do_elem (i) : foo; + append (octave_child (pid, f)); } void -octave_child_list::do_insert (pid_t pid, octave_child::dead_child_handler f) +OCL_REP::reap (void) { - // Insert item in first open slot, increasing size of list if - // necessary. + // Mark the record for PID invalid. - bool enlarge = true; + for (iterator p = begin (); p != end (); p++) + { + // The call to the octave_child::child_event_handler might + // invalidate the iterator (for example, by calling + // octave_child_list::remove), so we increment the iterator + // here. - for (int i = 0; i < curr_len; i++) - { - octave_child& tmp = list (i); + octave_child& oc = *p; - if (tmp.pid < 0) + if (oc.have_status) { - list (i) = octave_child (pid, f); - enlarge = false; - break; + oc.have_status = 0; + + octave_child::child_event_handler f = oc.handler; + + if (f && f (oc.pid, oc.status)) + oc.pid = -1; } } - 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 (curr_len) = octave_child (pid, f); - curr_len++; - } + remove_if (pid_equal (-1)); } -void -octave_child_list::do_remove (pid_t pid) +// Wait on our children and record any changes in their status. + +bool +OCL_REP::wait (void) { - // Mark the record for PID invalid. + bool retval = false; - for (int i = 0; i < curr_len; i++) + for (iterator p = begin (); p != end (); p++) { - octave_child& tmp = list (i); + octave_child& oc = *p; + + pid_t pid = oc.pid; + + if (pid > 0) + { + int status; - if (tmp.pid == pid) - { - tmp.pid = -1; - break; + if (waitpid (pid, &status, WNOHANG) > 0) + { + oc.have_status = 1; + + oc.status = status; + + retval = true; + + break; + } } } -} -int -octave_child_list::do_length (void) const -{ - return curr_len; -} - -octave_child& -octave_child_list::do_elem (int i) -{ - static octave_child foo; - - int n = do_length (); - - if (i >= 0 && i < n) - return list (i); - else - return foo; + return retval; } static int