Mercurial > octave
changeset 25319:56201aad3462 stable
avoid crash on exceptions thrown in handle class delete method
* ov-classdef (handle_cdef_object::~handle_cdef_object): Use same
technique as in octave_oncleanup::~octave_oncleanup to avoid crashes
if exceptions are thrown while executing handle class delete method
while inside C++ class destructor.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 26 Apr 2018 21:39:22 -0400 |
parents | b328ff3ce0f7 |
children | 2ad00275b79b 2540fde5f07b 4c14c002cabe |
files | libinterp/octave-value/ov-classdef.cc |
diffstat | 1 files changed, 40 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/octave-value/ov-classdef.cc Thu Nov 02 10:27:11 2017 -0700 +++ b/libinterp/octave-value/ov-classdef.cc Thu Apr 26 21:39:22 2018 -0400 @@ -1788,8 +1788,46 @@ handle_cdef_object::~handle_cdef_object (void) { - // Call classdef "delete()" method on object - get_class ().delete_object (get_class ()); + octave::unwind_protect frame; + + // Clear interrupts. + frame.protect_var (octave_interrupt_state); + octave_interrupt_state = 0; + + // Disallow quit(). + frame.protect_var (quit_allowed); + quit_allowed = false; + + interpreter_try (frame); + + try + { + // Call classdef "delete()" method on object + get_class ().delete_object (get_class ()); + } + catch (const octave::interrupt_exception&) + { + octave::interpreter::recover_from_exception (); + + warning ("interrupt occurred in handle class delete method"); + } + catch (const octave::execution_exception&) + { + std::string msg = last_error_message (); + warning ("error caught while executing handle class delete method:\n%s\n", + msg.c_str ()); + + } + catch (const octave::exit_exception&) + { + // This shouldn't happen since we disabled quit above. + warning ("exit disabled while executing handle class delete method"); + } + catch (...) // Yes, the black hole. We're in a d-tor. + { + // This shouldn't happen, in theory. + warning ("internal error: unhandled exception in handle class delete method"); + } #if DEBUG_TRACE std::cerr << "deleting " << get_class ().get_name ()