From: Nix <ni...@es...> - 2002-11-24 21:51:49
|
[Apologies for lack of References:, I am not a member of this list.] octave-forge needs adjustment to handle the new exception-based interrupt model in the latest CVS octave. I think this fixes it: 2002-11-24 Nix <ni...@es...> * make_sparse.h (SP_FATAL_ERR): Use octave_throw_interrupt_exception()... * make_sparse.h (includes): ... declared in quit.h. Index: octave-forge/main/sparse/make_sparse.h =================================================================== RCS file: /cvsroot/octave/octave-forge/main/sparse/make_sparse.h,v retrieving revision 1.9 diff -u -r1.9 make_sparse.h --- octave-forge/main/sparse/make_sparse.h 5 Nov 2002 19:21:07 -0000 1.9 +++ octave-forge/main/sparse/make_sparse.h 24 Nov 2002 21:40:14 -0000 @@ -89,7 +89,7 @@ // Thanks to To: Paul Kienzle <pki...@ki...> // for help with error handling #define SP_FATAL_ERR(str) { error("sparse: %s", str); \ - jump_to_top_level (); \ + octave_throw_interrupt_exception (); \ panic_impossible (); } // The SuperLU includes need to be first, @@ -132,6 +132,7 @@ #include <octave/ov-complex.h> #include <octave/ov-re-mat.h> #include <octave/ov-cx-mat.h> +#include <octave/quit.h> #include <octave/pager.h> #include <octave/pr-output.h> #include <octave/symtab.h> -- `I keep hearing about SF writers dying, but I never hear about SF writers being born. So I guess eventually there'll be none left.' -- Keith F. Lynch |
From: Paul K. <pki...@ja...> - 2002-11-25 01:12:51
|
The reason that won't work is because you need to something to catch it. That requires putting trapping code around each call to superLU to set the jump return address and reset it when done. Plus any loops outside of superLU need to have periodic checks if an interrupt has been triggered. The macros to do this are in quit.h, but I don't know the exact magic. Let me know if you are going to persue this, because it is top of my list (right behind family and work that is, which in this season puts it much too far back ;-) - Paul On Sun, Nov 24, 2002 at 09:46:18PM +0000, Nix wrote: > [Apologies for lack of References:, I am not a member of this list.] > > octave-forge needs adjustment to handle the new exception-based > interrupt model in the latest CVS octave. I think this fixes it: > > 2002-11-24 Nix <ni...@es...> > > * make_sparse.h (SP_FATAL_ERR): Use octave_throw_interrupt_exception()... > * make_sparse.h (includes): ... declared in quit.h. > > Index: octave-forge/main/sparse/make_sparse.h > =================================================================== > RCS file: /cvsroot/octave/octave-forge/main/sparse/make_sparse.h,v > retrieving revision 1.9 > diff -u -r1.9 make_sparse.h > --- octave-forge/main/sparse/make_sparse.h 5 Nov 2002 19:21:07 -0000 1.9 > +++ octave-forge/main/sparse/make_sparse.h 24 Nov 2002 21:40:14 -0000 > @@ -89,7 +89,7 @@ > // Thanks to To: Paul Kienzle <pki...@ki...> > // for help with error handling > #define SP_FATAL_ERR(str) { error("sparse: %s", str); \ > - jump_to_top_level (); \ > + octave_throw_interrupt_exception (); \ > panic_impossible (); } > > // The SuperLU includes need to be first, > @@ -132,6 +132,7 @@ > #include <octave/ov-complex.h> > #include <octave/ov-re-mat.h> > #include <octave/ov-cx-mat.h> > +#include <octave/quit.h> > #include <octave/pager.h> > #include <octave/pr-output.h> > #include <octave/symtab.h> > > -- > `I keep hearing about SF writers dying, but I never hear about SF > writers being born. So I guess eventually there'll be none left.' > -- Keith F. Lynch > > > > ------------------------------------------------------- > This sf.net email is sponsored by:ThinkGeek > Welcome to geek heaven. > http://thinkgeek.com/sf > _______________________________________________ > Octave-dev mailing list > Oct...@li... > https://lists.sourceforge.net/lists/listinfo/octave-dev |
From: Nix <ni...@es...> - 2002-11-25 20:38:11
|
On Sun, 24 Nov 2002, Paul Kienzle said: > The reason that won't work is because you need to something to catch it. But the catcher is in octave/toplev.cc; it throws right through our code and out the other side. (I'm sort of assuming that our destructors do all the necessary cleanup; if not, we'll need the occasional catch-and-rethrow ourselves.) Of course this code only handles errors, not interrupts. For that, see below :) > That requires putting trapping code around each call to superLU to set > the jump return address and reset it when done. Plus any loops outside > of superLU need to have periodic checks if an interrupt has been triggered. ... oh, damn and blast, SuperLU is C. I didn't notice and thought it was C++. OK, C that counts as foreign code, so calls into SuperLU will require BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE / END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE wrapped around them. That should let the code flow when interrupted by SIGINT within SuperLU go SIGINT -> signal handler in octave's src/sighandlers.cc -> octave_jump_to_enclosing_context() -> longjmp() to the END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE -> Octave's toplev.cc. > The macros to do this are in quit.h, but I don't know the exact magic. I think I've decrypted it. > Let me know if you are going to persue this, because it is top of my list It's top of mine too. Patch in an hour or so (this box is running rather slowly right now, alas, and it would be inurbane for me to antinice everyone else into oblivion). > (right behind family and work that is, which in this season puts it > much too far back ;-) :) -- `I keep hearing about SF writers dying, but I never hear about SF writers being born. So I guess eventually there'll be none left.' -- Keith F. Lynch |
From: Paul K. <pki...@ja...> - 2002-11-25 21:37:03
|
On Mon, Nov 25, 2002 at 08:35:11PM +0000, Nix wrote: > On Sun, 24 Nov 2002, Paul Kienzle said: > > The reason that won't work is because you need to something to catch it. > > But the catcher is in octave/toplev.cc; it throws right through our code > and out the other side. > > (I'm sort of assuming that our destructors do all the necessary cleanup; > if not, we'll need the occasional catch-and-rethrow ourselves.) > > Of course this code only handles errors, not interrupts. For that, see > below :) > > > That requires putting trapping code around each call to superLU to set > > the jump return address and reset it when done. Plus any loops outside > > of superLU need to have periodic checks if an interrupt has been triggered. > > ... oh, damn and blast, SuperLU is C. I didn't notice and thought it was > C++. Maybe all is not lost. I forgot that we are recompiling superlu ourselves. When I tested this a couple of years ago, I found that I could do something like: main.cc: #include <iostream> extern "C" { void throw_back(void); } extern "C" { void C_stuff(void); } class myexception {}; void throw_back(void) { throw myexception(); } int main(int argc, char *argv[]) { try { C_stuff(); std::cout << "not caught" << std::endl; } catch (myexception) { std::cout << "caught" << std::endl; } return 0; } lib.c: void C_stuff(void) { void throw_back(void); throw_back(); } Makefile: all: main.o lib.o g++ main.o lib.o -o throw_back main.o: main.cc g++ -c main.cc -o main.o lib.o: lib.c gcc -c -fexceptions lib.c -o lib.o This seems to still work. I don't know what to throw though. octave_throw_interrupt_exception() ? octave_throw_bad_alloc() ? If this works, I can push out a new octave-forge very soon, but Ctrl-C will not be responsive within superLU. For Ctrl-C we need to put OCTAVE_QUIT in all the inner loops of *.{cc,h} and wrap calls to superLU with BEGIN/END_INTERRUPT_WITH_EXCEPTIONS. At least I think that's what we are supposed to do. It's not clear how we can clean up a superLU malloc which was interrupted during initialization. I believe that's why garbage collection was invented. > > OK, C that counts as foreign code, so calls into SuperLU will require > BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE / > END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE wrapped around them. That > should let the code flow when interrupted by SIGINT within SuperLU go > > SIGINT -> signal handler in octave's src/sighandlers.cc -> > octave_jump_to_enclosing_context() -> longjmp() to the > END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE -> Octave's toplev.cc. > > > The macros to do this are in quit.h, but I don't know the exact magic. > > I think I've decrypted it. > > > Let me know if you are going to persue this, because it is top of my list > > It's top of mine too. Patch in an hour or so (this box is running rather > slowly right now, alas, and it would be inurbane for me to antinice > everyone else into oblivion). > > > (right behind family and work that is, which in this season puts it > > much too far back ;-) > > :) > > -- > `I keep hearing about SF writers dying, but I never hear about SF > writers being born. So I guess eventually there'll be none left.' > -- Keith F. Lynch > |
From: Nix <ni...@es...> - 2002-11-26 21:34:30
|
On Mon, 25 Nov 2002, Paul Kienzle yowled: > On Mon, Nov 25, 2002 at 08:35:11PM +0000, Nix wrote: >> ... oh, damn and blast, SuperLU is C. I didn't notice and thought it was >> C++. > > Maybe all is not lost. I forgot that we are recompiling superlu ourselves. > When I tested this a couple of years ago, I found that I could do something > like: [throw through C] > This seems to still work. I don't know what to throw though. Yes, this will always work; we'd be in some trouble being ISO C++ compliant otherwise --- the Standard requires throws through std::qsort() and std::bsearch() to work, in s17.3.4.8.2 --- and POSIX has a good few callback-style routines, which it would be nice to allow exceptions to be thrown through. I guess we could have done it by reimplementing qsort() and bsearch() in libstdc++-v3, but that would have been ugly. (Obviously, exception throws through non-GCC-compiled C code won't work, except on the IA64, which has hardware support for exceptions. :) ) One problem is that this is a rather GCC-specific solution :( I'm sure there are compilers out there that *don't* support throwing through C code. But luckily we don't need to do this at all. (See below.) > > octave_throw_interrupt_exception() ? > octave_throw_bad_alloc() ? Neither. > If this works, I can push out a new octave-forge very soon, > but Ctrl-C will not be responsive within superLU. > > For Ctrl-C we need to put OCTAVE_QUIT in all the inner loops of *.{cc,h} No need :) > and wrap calls to superLU with BEGIN/END_INTERRUPT_WITH_EXCEPTIONS. > At least I think that's what we are supposed to do. No need for any of that; the _IMMEDIATELY_ variants of those macros set up a setjmp() / throw layer. The Octave signal handlers in src/sighandlers.cc spot that we're inside an _IMMEDIATELY_ wrapper (because `octave_interrupt_immediately' is nonzero) and (sig)longjmp there for us. > It's not clear how we can clean up a superLU malloc which was interrupted > during initialization. I believe that's why garbage collection was > invented. You can't clean that up, but then we've *never* been able to clean that up. At least this way destructors for C++ objects get called :) (Hell, there's a worse case than that: the SIGINT is asynchronous, so it can arrive in the middle of a malloc(). If it does that, we're completely screwed and the heap is fubared. But this, too, has always been the case, and there don't seem to be many bug reports that can be traced to screwed heaps. So I guess this is rare enough to ignore.) Leaving the bit below because it's still relevant: >> OK, C that counts as foreign code, so calls into SuperLU will require >> BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE / >> END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE wrapped around them. That >> should let the code flow when interrupted by SIGINT within SuperLU go >> >> SIGINT -> signal handler in octave's src/sighandlers.cc -> >> octave_jump_to_enclosing_context() -> longjmp() to the >> END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE -> Octave's toplev.cc. >> >> > The macros to do this are in quit.h, but I don't know the exact magic. >> >> I think I've decrypted it. >> >> > Let me know if you are going to persue this, because it is top of my list >> >> It's top of mine too. Patch in an hour or so (this box is running rather >> slowly right now, alas, and it would be inurbane for me to antinice >> everyone else into oblivion). I got stalled by wondering how best to wrap *all* calls into SuperLU. I guess that a thin C++ wrapper around SuperLU is indicated, each of which does careful BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE / END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE calls. --- oh, this is only needed in computationally expensive stuff. In cheap calls we can just ignore it and leave the calls undecorated, because the user won't interrupt in there and won't notice the delay even if he does. (Decorating such calls is probably a bad idea, actually, because the setup and teardown for the _INTERRUPT_IMMEDIATELY_ stuff isn't free.) So probably that's just a few potentially-expensive SuperLU calls we need to decorate. Any idea which they are? I haven't much of a clue :) -- `I keep hearing about SF writers dying, but I never hear about SF writers being born. So I guess eventually there'll be none left.' -- Keith F. Lynch |
From: John W. E. <jw...@be...> - 2002-11-27 19:38:52
|
On 26-Nov-2002, Nix <ni...@es...> wrote: | On Mon, 25 Nov 2002, Paul Kienzle yowled: | | > If this works, I can push out a new octave-forge very soon, | > but Ctrl-C will not be responsive within superLU. | > | > For Ctrl-C we need to put OCTAVE_QUIT in all the inner loops of *.{cc,h} | | No need :) Why not? I think they do need to be in the Octave interface glue code. | > and wrap calls to superLU with BEGIN/END_INTERRUPT_WITH_EXCEPTIONS. | > At least I think that's what we are supposed to do. Yes. I updated my copy of the octave-forge code from CVS and it looks like Paul has done the right thing, though it could probably be improved to handle freeing resources in more places in the Octave glue code. But, as Paul mentioned, whether we should actually do that work depends on whether we are going to actually integrate the SuperLU code in Octave. I think the SuperLU code is now at least as good as it was with the previous interrupt handling model (which was generally very bad because of the jump out of the signal handler). | No need for any of that; the _IMMEDIATELY_ variants of those macros set | up a setjmp() / throw layer. The Octave signal handlers in | src/sighandlers.cc spot that we're inside an _IMMEDIATELY_ wrapper | (because `octave_interrupt_immediately' is nonzero) and (sig)longjmp | there for us. | | > It's not clear how we can clean up a superLU malloc which was interrupted | > during initialization. I believe that's why garbage collection was | > invented. | | You can't clean that up, but then we've *never* been able to clean that | up. At least this way destructors for C++ objects get called :) | | (Hell, there's a worse case than that: the SIGINT is asynchronous, so it | can arrive in the middle of a malloc(). If it does that, we're | completely screwed and the heap is fubared. But this, too, has always | been the case, and there don't seem to be many bug reports that can be | traced to screwed heaps. So I guess this is rare enough to ignore.) Right. This is one of the reasons it is bad to jump out of a signal handler. If instead the signal handler sets some flag indicating that it has been called and returns so that the jump only happens when it is safe, we are OK. But unless SuperLU is written with signal handling in mind, then this will require some changes. The "jump from the signal handler" model is generally OK for the old Fortran 77 numerical code because in most cases that code doesn't acquire any resources. All memory allocations are handled outside of the call to the Fortran 77 subroutine and most of the old Fortran numerical code doesn't open files or even modify global variables. | I got stalled by wondering how best to wrap *all* calls into SuperLU. I | guess that a thin C++ wrapper around SuperLU is indicated, each of which | does careful BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE / | END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE calls. | | --- oh, this is only needed in computationally expensive stuff. In cheap | calls we can just ignore it and leave the calls undecorated, because the | user won't interrupt in there and won't notice the delay even if he | does. (Decorating such calls is probably a bad idea, actually, because | the setup and teardown for the _INTERRUPT_IMMEDIATELY_ stuff isn't | free.) Right. This is the same as the choice we have with calls to Fortran code. We either use F77_XFCN (sets up for a potential longjmp call, so should be used for expensive calls, or ones where we can't easily determine how long they will take) or F77_FUNC (no longjmp setup, so we expect it to return quickly). jwe |
From: Paul K. <pki...@ja...> - 2002-11-27 05:18:11
|
I've sprinkled very ugly OCTAVE_QUIT and BEGIN/END_INTERRUPT_IN_FOREIGN_CODE macros throughout the sparse functions. sp_test continues to work, even after Ctrl-C. But if you have top running, you can see that Ctrl-C leads to big memory leaks. There is a new debug_on_interrupt flag. I have confirmed that it will drop you into a debug prompt on Ctrl-C, but I haven't checked that it is in a valid state when you do. In particular, I don't know if the current line has been run to completion, or if dbg_cont will cause it to be executed again. The few simple tests I did (sp_test followed by Ctrl-C followed by dbg_cont) seem to work. I don't know how to generate internal sparse errors, so I don't know that I have SuperLU compiled correctly to throw fatal errors through C code. I'm hoping that these errors will all be memory errors so that throwing a bad_alloc exception is appropriate. Elsewhere sparse is using SP_FATAL_ERROR rather than laboriously returning the error up the stack. E.g., sparse(1,1,[1,2]) Since it is SP_FATAL_ERROR which is throwing the bad_alloc exception, this is erroneously labeled a "memory exhausted" error. I'm willing to live with that for the moment, but I'm happy to accept patches to fix it properly. I don't want to put to much energy into it until I know which sparse package John is going to use in Octave. I've seen reports on the web that umfpack and mumps are both faster than superlu, so maybe we will change packages. I know in particular that umfpack does propogates error codes rather than punting to a fatal error handler, which will remove at least some of the problems in the code. I can now build octave-forge against 2.1.40 without error, at least the subset that I'm installing. Please test and report any errors. Paul Kienzle pki...@us... On Tue, Nov 26, 2002 at 09:33:12PM +0000, Nix wrote: > On Mon, 25 Nov 2002, Paul Kienzle yowled: > > On Mon, Nov 25, 2002 at 08:35:11PM +0000, Nix wrote: > >> ... oh, damn and blast, SuperLU is C. I didn't notice and thought it was > >> C++. > > > > Maybe all is not lost. I forgot that we are recompiling superlu ourselves. > > When I tested this a couple of years ago, I found that I could do something > > like: > > [throw through C] > > This seems to still work. I don't know what to throw though. > > Yes, this will always work; we'd be in some trouble being ISO C++ > compliant otherwise --- the Standard requires throws through > std::qsort() and std::bsearch() to work, in s17.3.4.8.2 --- and POSIX > has a good few callback-style routines, which it would be nice to allow > exceptions to be thrown through. > > I guess we could have done it by reimplementing qsort() and bsearch() in > libstdc++-v3, but that would have been ugly. > > (Obviously, exception throws through non-GCC-compiled C code won't work, > except on the IA64, which has hardware support for exceptions. :) ) > > > One problem is that this is a rather GCC-specific solution :( I'm sure > there are compilers out there that *don't* support throwing through C > code. > > But luckily we don't need to do this at all. (See below.) > > > > > octave_throw_interrupt_exception() ? > > octave_throw_bad_alloc() ? > > Neither. > > > If this works, I can push out a new octave-forge very soon, > > but Ctrl-C will not be responsive within superLU. > > > > For Ctrl-C we need to put OCTAVE_QUIT in all the inner loops of *.{cc,h} > > No need :) > > > and wrap calls to superLU with BEGIN/END_INTERRUPT_WITH_EXCEPTIONS. > > At least I think that's what we are supposed to do. > > No need for any of that; the _IMMEDIATELY_ variants of those macros set > up a setjmp() / throw layer. The Octave signal handlers in > src/sighandlers.cc spot that we're inside an _IMMEDIATELY_ wrapper > (because `octave_interrupt_immediately' is nonzero) and (sig)longjmp > there for us. > > > It's not clear how we can clean up a superLU malloc which was interrupted > > during initialization. I believe that's why garbage collection was > > invented. > > You can't clean that up, but then we've *never* been able to clean that > up. At least this way destructors for C++ objects get called :) > > (Hell, there's a worse case than that: the SIGINT is asynchronous, so it > can arrive in the middle of a malloc(). If it does that, we're > completely screwed and the heap is fubared. But this, too, has always > been the case, and there don't seem to be many bug reports that can be > traced to screwed heaps. So I guess this is rare enough to ignore.) > > Leaving the bit below because it's still relevant: > > >> OK, C that counts as foreign code, so calls into SuperLU will require > >> BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE / > >> END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE wrapped around them. That > >> should let the code flow when interrupted by SIGINT within SuperLU go > >> > >> SIGINT -> signal handler in octave's src/sighandlers.cc -> > >> octave_jump_to_enclosing_context() -> longjmp() to the > >> END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE -> Octave's toplev.cc. > >> > >> > The macros to do this are in quit.h, but I don't know the exact magic. > >> > >> I think I've decrypted it. > >> > >> > Let me know if you are going to persue this, because it is top of my list > >> > >> It's top of mine too. Patch in an hour or so (this box is running rather > >> slowly right now, alas, and it would be inurbane for me to antinice > >> everyone else into oblivion). > > I got stalled by wondering how best to wrap *all* calls into SuperLU. I > guess that a thin C++ wrapper around SuperLU is indicated, each of which > does careful BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE / > END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE calls. > > --- oh, this is only needed in computationally expensive stuff. In cheap > calls we can just ignore it and leave the calls undecorated, because the > user won't interrupt in there and won't notice the delay even if he > does. (Decorating such calls is probably a bad idea, actually, because > the setup and teardown for the _INTERRUPT_IMMEDIATELY_ stuff isn't > free.) > > So probably that's just a few potentially-expensive SuperLU calls we > need to decorate. > > Any idea which they are? I haven't much of a clue :) > > -- > `I keep hearing about SF writers dying, but I never hear about SF > writers being born. So I guess eventually there'll be none left.' > -- Keith F. Lynch > > > > ------------------------------------------------------- > This SF.net email is sponsored by: Get the new Palm Tungsten T > handheld. Power & Color in a compact size! > http://ads.sourceforge.net/cgi-bin/redirect.pl?palm0002en > _______________________________________________ > Octave-dev mailing list > Oct...@li... > https://lists.sourceforge.net/lists/listinfo/octave-dev |
From: John W. E. <jw...@be...> - 2002-11-27 17:04:40
|
On 27-Nov-2002, Paul Kienzle <pki...@ja...> wrote: | I've sprinkled very ugly OCTAVE_QUIT and BEGIN/END_INTERRUPT_IN_FOREIGN_CODE | macros throughout the sparse functions. | | sp_test continues to work, even after Ctrl-C. But if you have top running, | you can see that Ctrl-C leads to big memory leaks. This would have been true with the old method of handling interrupts too, only it would have been even worse because it just jumped back to the top level, ignoring all resource allocations on the way back to the top. Only those that were explicitly added to Octave's unwind_protect stack would have been deallocated/restored, and in most cases, Octave's unwind_protect stack is used not to protect resource allocations, but to ensure that temporary modifications to global variables are restored. Now you can control where OCTAVE_QUIT is called. The resource allocation problem can be solved by ensuring that resources are allocated in constructors and deallocated in destructors. If that's not possible, then another approach would be to do something like if (octave_interrupt_state) { // Deallocate resources/restore state/etc here. octave_interrupt_state = 0; octave_throw_interrupt_exception (); } instead of using OCTAVE_QUIT (which is the same as the code above, except it doesn't explicitly deallocate or restore any resources). | There is a new debug_on_interrupt flag. I have confirmed that it will | drop you into a debug prompt on Ctrl-C, but I haven't checked that it | is in a valid state when you do. In particular, I don't know if the | current line has been run to completion, or if dbg_cont will cause it | to be executed again. The few simple tests I did (sp_test followed | by Ctrl-C followed by dbg_cont) seem to work. I think it should be OK, because when debug_on_interrupt is set, the SIGINT handler just does octave_debug_on_interrupt_state = true; and returns. Unless you send another interrupt before entering the debugger, octave_interrupt_state will not be set, and Octave will continue executing until the statement evaluation loop is hit, where we check the value of octave_debug_on_interrupt_state. At that point, we are preparing to evaluate the next statement, so everything should be in a sane state. | I don't know how to generate internal sparse errors, so I don't know that | I have SuperLU compiled correctly to throw fatal errors through C | code. For testing, I suppose you could just modify the SuperLU code to generate one of these errors for a valid call, or modify the way SuperLU is called so that the call will generate an error. We have the same problem with testing what happens when Lapack code is called with incorrect arguments. Normally there is not supposed to be any way to make that happen from Octave, so to test it you have to introduce an error in code, then remove it after testing is done. | I'm hoping that these errors will all be memory errors so that throwing a | bad_alloc exception is appropriate. OK. I haven't really looked at SuperLU, so I don't know, but if there are other possible errors, it would be nice to distinguish between bad allocations and other problems. | Elsewhere sparse is using SP_FATAL_ERROR rather than laboriously | returning the error up the stack. E.g., sparse(1,1,[1,2]) | Since it is SP_FATAL_ERROR which is throwing the bad_alloc exception, | this is erroneously labeled a "memory exhausted" error. I'm willing | to live with that for the moment, but I'm happy to accept patches to | fix it properly. OK. | I don't want to put to much energy into it until I know which sparse | package John is going to use in Octave. I've seen reports on the web that | umfpack and mumps are both faster than superlu, so maybe we will change | packages. I know in particular that umfpack does propogates error codes | rather than punting to a fatal error handler, which will remove at least | some of the problems in the code. I will try to respond later today to your other message about sparse packages that we might be able to use. Thanks, jwe |
From: Paul K. <pki...@ja...> - 2002-11-27 21:09:10
|
On Wed, Nov 27, 2002 at 01:38:22PM -0600, John W. Eaton wrote: > On 26-Nov-2002, Nix <ni...@es...> wrote: > | (Hell, there's a worse case than that: the SIGINT is asynchronous, so it > | can arrive in the middle of a malloc(). If it does that, we're > | completely screwed and the heap is fubared. But this, too, has always > | been the case, and there don't seem to be many bug reports that can be > | traced to screwed heaps. So I guess this is rare enough to ignore.) > > Right. This is one of the reasons it is bad to jump out of a signal > handler. If instead the signal handler sets some flag indicating that > it has been called and returns so that the jump only happens when it > is safe, we are OK. But unless SuperLU is written with signal > handling in mind, then this will require some changes. I do find it ugly having to decide for each loop whether or not an octave quit is desired. The alternative approach is garbage collection is it not? Assuming sigsetjmp/siglongjmp work as advertised, then with a garbage collection system you could eventually clean up after an interrupt. You would have to be careful to write your resource allocator code safely: allocate_resource() { allocating = 1 grab resource and register it allocating = 0 if (interrupted) siglongjump } interrupt_signal() { if (interrupted) return if (allocating) interrupted=1 else siglongjmp } eval_once() { if (sigsetjmp()) collect garbage else do next operation } Then the bulk of your code, and your numeric code in particular, doesn't have to glance obsessively at the quit flag to see whether the user has become bored of waiting yet. This should make your code faster and easier to write. In this case, resource allocation include things like unwind_protect as it is currently used to protect global variables as well as fopen, and malloc. Would this be any better than sprinkling BEGIN/END_INTERRUPT and OCTAVE_QUIT all over the code? - Paul |
From: John W. E. <jw...@be...> - 2002-11-27 21:56:40
|
On 27-Nov-2002, Paul Kienzle <pki...@ja...> wrote: | I do find it ugly having to decide for each loop whether or not an octave | quit is desired. The alternative approach is garbage collection is it | not? Assuming sigsetjmp/siglongjmp work as advertised, then with a | garbage collection system you could eventually clean up after an interrupt. | You would have to be careful to write your resource allocator code safely: | | allocate_resource() { | allocating = 1 | grab resource and register it | allocating = 0 | if (interrupted) siglongjump | } | | interrupt_signal() { | if (interrupted) return | if (allocating) interrupted=1 | else siglongjmp | } | | eval_once() { | if (sigsetjmp()) collect garbage | else do next operation | } | | Then the bulk of your code, and your numeric code in particular, | doesn't have to glance obsessively at the quit flag to see whether | the user has become bored of waiting yet. This should make your | code faster and easier to write. In this case, resource allocation | include things like unwind_protect as it is currently used to | protect global variables as well as fopen, and malloc. | | Would this be any better than sprinkling BEGIN/END_INTERRUPT and | OCTAVE_QUIT all over the code? The method above requires doing something special for all resource allocations and then undoing that at the point of deallocation. This would be in addition to whatever already happens in the constructor and destructor (which now may or may not be called). * Which way adds less overhead? It may be more expensive to add/delete tags in every constructor/destructor pair than it is to check the interrupt state in a few strategic locations. * Is it easier or harder to write and maintain? Every allocation, not just memory allocations, must be tagged specially. * Is it more reliable? It might not be practical to modify all the constructors for all the classes so that they can register the resources that they allocate)? My guess is that the method above requires more care than the way Octave currently works (with the signal handler setting the interrupt state and OCTAVE_QUIT to check it). If you omit OCTAVE_QUIT in some long-running loop, Octave is just unresponsive to interrupts. If you forget to register an allocation, then we will have resource leaks, and potentially, you could leave the interpreter in an inconsistent state. jwe |