octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Working patch for FFTW 3.0.x and Nd FFT's


From: John W. Eaton
Subject: Re: Working patch for FFTW 3.0.x and Nd FFT's
Date: Wed, 18 Feb 2004 14:50:38 -0600

On 17-Feb-2004, Paul Kienzle <address@hidden> wrote:

| Is it possible to fall back to a long jump for the impatient?
| That is, if you press Ctrl-C twice,  can you trigger a long
| jump directly from the signal?
| 
| The main reason I see why not to do it this way is
| because it may leak memory, or otherwise fail to
| free resources.
| 
| This would be a problem in the last case I encountered
| it, which was full(sparse(5000,5000,1)), which failed
| to return immediately when Ctrl-C was pressed.

I think the only safe thing to do in this case is to offer to abort,
optionally attempting to save the top-level workspace.  What about
something like the following patch?  With it, I see this behavior:

  octave:1> x = rand (10000000, 1);
  octave:2> fft (x);                  ## C-c four times while this runs
  abort [y/N]? y
  save top-level workspace [y/N]? y
  panic: Interrupt -- stopping myself...
  attempting to save variables to `octave-core'...
  save to `octave-core' complete

Unfortunately, there is no warning about the size of the workspace.
In this case, it turned into a 189MB file (text format -- maybe that
should also be changed?), which took 10-15 seconds to save to a
relatviely fast local disk.

| It would be nice to convert Ctrl-C into a C++ exception
| directly.  IIRC, the ada runtime is supposed to be able
| to convert signals into exceptions, but I was never able
| to find it in the gnu ada code.  Maybe they don't.

I'm not sure, but I think the only safe way to do that is to throw the
C++ exception outside the signal handler.

| The alternative approach is radical: garbage collection.
| This is not something any of us have time to consider
| in a pre-2.2 release.

Garbage collection could solve the memory allocation problem, but I
don't think it solves the general resource problem.  What happens to
a local fstream object created in some function if you just jump back
to the top-level from the a signal handler?  Do you have to register
each of those with something like an unwind-protect handler so that it
will be properly closed, or can you somehow make garbage collection
also clean up those kinds of temporary C++ objects?  The nice thing
about the way that we are doing things now is that as long as
resources are acquired in constructors and released in destructors,
they are cleaned up when an exception is thrown.

jwe


src/ChangeLog:

2004-02-18  John W. Eaton  <address@hidden>

        * sighandlers.cc (my_friendly_exit): New optional arg, save_vars.
        Only call save_user_variables if save_vars is true.
        (sigint_handler): If interactive, offer to abort and save
        workspace after three consecutive interrupts.
        (sigint_handler, sigpipe_handler, sigfpe_handler):
        Increment octave_interrupt_handler instead of setting it to 1.

 
Index: src/sighandlers.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/sighandlers.cc,v
retrieving revision 1.78
diff -u -r1.78 sighandlers.cc
--- src/sighandlers.cc  16 Dec 2003 05:11:26 -0000      1.78
+++ src/sighandlers.cc  18 Feb 2004 20:44:25 -0000
@@ -46,6 +46,7 @@
 #include "pager.h"
 #include "pt-bp.h"
 #include "sighandlers.h"
+#include "sysdep.h"
 #include "syswait.h"
 #include "toplev.h"
 #include "utils.h"
@@ -93,7 +94,8 @@
 #endif
 
 static void
-my_friendly_exit (const char *sig_name, int sig_number)
+my_friendly_exit (const char *sig_name, int sig_number,
+                 bool save_vars = true)
 {
   static bool been_there_done_that = false;
 
@@ -112,7 +114,8 @@
 
       std::cerr << "panic: " << sig_name << " -- stopping myself...\n";
 
-      save_user_variables ();
+      if (save_vars)
+       save_user_variables ();
 
       if (sig_number < 0)
        exit (1);
@@ -235,7 +238,7 @@
   // here?
 
   if (can_interrupt)
-    octave_interrupt_state = 1;
+    octave_interrupt_state++;
 
   SIGHANDLER_RETURN (0);
 }
@@ -303,11 +306,7 @@
 // for SIGINT only.
 
 static RETSIGTYPE
-#if defined (ACK_USES_SIG) || defined (REINSTALL_USES_SIG)
 sigint_handler (int sig)
-#else
-sigint_handler (int)
-#endif
 {
   MAYBE_ACK_SIGNAL (sig);
 
@@ -334,7 +333,47 @@
       if (octave_interrupt_immediately)
        octave_jump_to_enclosing_context ();
       else
-       octave_interrupt_state = 1;
+       {
+         octave_interrupt_state++;
+
+         if (interactive)
+           {
+             if (octave_interrupt_state > 3)
+               {
+                 // XXX FIXME XXX -- might want to attempt to flush
+                 // any pending input first...
+
+                 std::cerr << "abort [y/N]? ";
+
+                 int c = octave_kbhit ();
+
+                 std::cerr << static_cast<char> (c) << std::endl;
+
+                 if (c == 'y' || c == 'Y')
+                   {
+                     std::cerr << "save top-level workspace [y/N]? ";
+
+                     c = octave_kbhit ();
+
+                     std::cerr << static_cast<char> (c) << std::endl;
+
+                     my_friendly_exit (sys_siglist[sig], sig,
+                                       (c == 'y' || c == 'Y'));
+                   }
+                 else
+                   {
+                     // We will still eventually interrupt and jump to
+                     // the top level even if no additional interrupts
+                     // happen, but we will have to wait until it is
+                     // safe to do so.  It will take 3 more
+                     // consecutive interrupts before we offer to
+                     // abort again.
+
+                     octave_interrupt_state = 1;
+                   }
+               }
+           }
+       }
     }
 
   SIGHANDLER_RETURN (0);
@@ -357,7 +396,7 @@
   // here?
 
   if (pipe_handler_error_count  > 100)
-    octave_interrupt_state = 1;
+    octave_interrupt_state++;
 
   SIGHANDLER_RETURN (0);
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]