# HG changeset patch # User Jaroslav Hajek # Date 1260432887 -3600 # Node ID 80432f0ee89593cf5149ef5edab1af080e8bf4c8 # Parent 59ed1155771579ca0c7ff18049cc472a46d3af88 improve octave_shlib for safer shared libs treatment diff -r 59ed11557715 -r 80432f0ee895 liboctave/ChangeLog --- a/liboctave/ChangeLog Thu Dec 10 02:09:53 2009 -0500 +++ b/liboctave/ChangeLog Thu Dec 10 09:14:47 2009 +0100 @@ -1,3 +1,8 @@ +2009-12-09 Jaroslav Hajek + + * oct-shlib.h (octave_shlib): Rewrite. + * oct-shlib.cc (octave_shlib): Rewrite. + 2009-12-09 John W. Eaton * oct-time.cc (octave_base_tm::strftime): Call nstrftime instead diff -r 59ed11557715 -r 80432f0ee895 liboctave/oct-shlib.cc --- a/liboctave/oct-shlib.cc Thu Dec 10 02:09:53 2009 -0500 +++ b/liboctave/oct-shlib.cc Thu Dec 10 09:14:47 2009 +0100 @@ -1,6 +1,7 @@ /* Copyright (C) 1999, 2000, 2002, 2003, 2005, 2006, 2007, 2008 John W. Eaton +Copyright (C) 2009 VZLU Prague This file is part of Octave. @@ -60,77 +61,69 @@ #include "oct-shlib.h" #include "str-vec.h" -class -octave_base_shlib : public octave_shlib +octave_shlib::shlib_rep::shlib_rep (const std::string& f) + : count (1), file (f), tm_loaded () { -public: - - octave_base_shlib (void) - : octave_shlib (octave_xshlib ()), file (), fcn_names (), - tm_loaded (static_cast (0)) - { count = 1; } - - octave_base_shlib (const std::string& f) - : octave_shlib (octave_xshlib ()), file (f), fcn_names (), - tm_loaded (static_cast (0)) - { count = 1; } - - ~octave_base_shlib (void) { } - - void open (const std::string&) { } - - // FIXME -- instead of returning a direct pointer to a function, - // perhaps this should return an object containing the pointer. - // Then we could do the reference counting without relying on users - // of this class to call remove at the appropriate time. However, - // when users accessed the internal pointer, they would still need - // to know that the pointer is only valid while the container is - // valid (similar to the std::string::c_str method). - - void *search (const std::string&, name_mangler = 0) { return 0; } - - void close (octave_shlib::close_hook = 0) { } - - bool remove (const std::string& fcn_name); + instances[f] = this; - bool is_open (void) const { return false; } - - bool is_out_of_date (void) const; - - size_t number_of_functions_loaded (void) const { return fcn_names.size (); } - - std::string file_name (void) const { return file; } - - octave_time time_loaded (void) const { return tm_loaded; } - -protected: - - typedef std::map::iterator fcn_names_iterator; - typedef std::map::const_iterator fcn_names_const_iterator; - - std::string file; - - std::map fcn_names; - - octave_time tm_loaded; - - void stamp_time (void); - - void add_to_fcn_names (const std::string& name); - - void do_close_hook (octave_shlib::close_hook = 0); - - void tabula_rasa (void); - - // No copying! - - octave_base_shlib (const octave_base_shlib&); - - octave_base_shlib& operator = (const octave_base_shlib&); -}; + if (is_out_of_date ()) + (*current_liboctave_warning_with_id_handler) + ("Octave:warn-future-time-stamp", + "timestamp on file %s is in the future", file.c_str ()); +} bool -octave_base_shlib::remove (const std::string& fcn_name) +octave_shlib::shlib_rep::is_out_of_date (void) const +{ + file_stat fs (file); + return fs.is_newer (tm_loaded); +} + +void +octave_shlib::shlib_rep::fake_reload (void) +{ + // We can't actually reload the library, but we'll pretend we did. + file_stat fs (file); + if (fs.is_newer (tm_loaded)) + { + tm_loaded = fs.mtime (); + + (*current_liboctave_warning_handler) + ("library %s not reloaded due to existing references", file.c_str ()); + } +} + +octave_shlib::shlib_rep * +octave_shlib::shlib_rep::get_instance (const std::string& f, bool fake) +{ + shlib_rep *retval = 0; + std::map::iterator p = instances.find (f); + if (p != instances.end ()) + { + retval = p->second; + retval->count++; + if (fake) + retval->fake_reload (); + } + else + retval = new_instance (f); + + return retval; +} + +void +octave_shlib::shlib_rep::add_fcn_name (const std::string& name) +{ + fcn_names_iterator p = fcn_names.find (name); + + if (p == fcn_names.end ()) + fcn_names[name] = 1; + else + ++(p->second); +} + +bool +octave_shlib::shlib_rep::remove_fcn_name (const std::string& fcn_name) { bool retval = false; @@ -145,71 +138,35 @@ return retval; } -bool -octave_base_shlib::is_out_of_date (void) const -{ - file_stat fs (file); - - return fs.is_newer (tm_loaded); -} - void -octave_base_shlib::stamp_time (void) -{ - tm_loaded.stamp (); - - file_stat fs (file); - - if (fs.is_newer (tm_loaded)) - (*current_liboctave_warning_with_id_handler) - ("Octave:warn-future-time-stamp", - "timestamp on file %s is in the future", file.c_str ()); -} - -void -octave_base_shlib::add_to_fcn_names (const std::string& name) -{ - fcn_names_iterator p = fcn_names.find (name); - - if (p == fcn_names.end ()) - fcn_names[name] = 1; - else - ++(p->second); -} - -void -octave_base_shlib::do_close_hook (octave_shlib::close_hook cl_hook) +octave_shlib::shlib_rep::do_close_hook (octave_shlib::close_hook cl_hook) { for (fcn_names_iterator p = fcn_names.begin (); p != fcn_names.end (); p++) cl_hook (p->first); + + fcn_names.clear (); } -void -octave_base_shlib::tabula_rasa (void) -{ - file = ""; +std::map octave_shlib::shlib_rep::instances; - fcn_names.clear (); - - tm_loaded = static_cast (0); -} +octave_shlib::shlib_rep octave_shlib::nil_rep; #if defined (HAVE_DLOPEN_API) class -octave_dlopen_shlib : public octave_base_shlib +octave_dlopen_shlib : public octave_shlib::shlib_rep { public: - octave_dlopen_shlib (void); + octave_dlopen_shlib (const std::string& f); ~octave_dlopen_shlib (void); - void open (const std::string& f); + void *search (const std::string& name, octave_shlib::name_mangler mangler = 0); - void *search (const std::string& name, name_mangler mangler = 0); - - void close (octave_shlib::close_hook cl_hook = 0); + // FIXME: this is possibly redundant because failure to open a library will + // normally throw an exception, avoiding the construction of an invalid + // library. Leave it here for possible future use. bool is_open (void) const { return (library != 0); } @@ -224,48 +181,36 @@ void *library; }; -octave_dlopen_shlib::octave_dlopen_shlib (void) - : octave_base_shlib (), library (0) +octave_dlopen_shlib::octave_dlopen_shlib (const std::string& f) + : octave_shlib::shlib_rep (f), library (0) { + int flags = 0; + + // Use RTLD_NOW to resolve all symbols before dlopen returns. + // By using this option, dlopen will detect errors and Octave + // won't exit if there are unresolved symbols in the file we are + // loading, and we may even get a useful diagnostic. +#if defined (RTLD_NOW) + flags |= RTLD_NOW; +#endif + + library = dlopen (file.c_str (), flags); + + if (! library) + { + const char *msg = dlerror (); + + if (! msg) + (*current_liboctave_error_handler) ("%s", msg); + else + (*current_liboctave_error_handler) ("%s: failed to load", file.c_str ()); + } } octave_dlopen_shlib::~octave_dlopen_shlib (void) { - close (); -} - -void -octave_dlopen_shlib::open (const std::string& f) -{ - if (! is_open ()) - { - file = f; - - int flags = 0; - - // Use RTLD_NOW to resolve all symbols before dlopen returns. - // By using this option, dlopen will detect errors and Octave - // won't exit if there are unresolved symbols in the file we are - // loading, and we may even get a useful diagnostic. -#if defined (RTLD_NOW) - flags |= RTLD_NOW; -#endif - - library = dlopen (file.c_str (), flags); - - if (library) - stamp_time (); - else - { - const char *msg = dlerror (); - - if (msg) - (*current_liboctave_error_handler) ("%s", msg); - } - } - else - (*current_liboctave_error_handler) - ("shared library %s is already open", file.c_str ()); + if (library) + dlclose (library); } void * @@ -282,9 +227,6 @@ sym_name = mangler (name); function = dlsym (library, sym_name.c_str ()); - - if (function) - add_to_fcn_names (name); } else (*current_liboctave_error_handler) @@ -293,38 +235,18 @@ return function; } -void -octave_dlopen_shlib::close (octave_shlib::close_hook cl_hook) -{ - if (is_open ()) - { - if (cl_hook) - do_close_hook (cl_hook); - - dlclose (library); - - library = 0; - - tabula_rasa (); - } -} - #elif defined (HAVE_SHL_LOAD_API) class -octave_shl_load_shlib : public octave_base_shlib +octave_shl_load_shlib : public octave_shlib::shlib_rep { public: - octave_shl_load_shlib (void); + octave_shl_load_shlib (const std::string& f); ~octave_shl_load_shlib (void); - void open (const std::string& f); - - void *search (const std::string& name, name_mangler mangler = 0); - - void close (octave_shlib::close_hook cl_hook = 0); + void *search (const std::string& name, octave_shlib::name_mangler mangler = 0); bool is_open (void) const { return (library != 0); } @@ -339,36 +261,24 @@ shl_t library; }; -octave_shl_load_shlib::octave_shl_load_shlib (void) - : octave_base_shlib (), library (0) +octave_shl_load_shlib::octave_shl_load_shlib (const std::string& f) + : octave_shlib::shlib_rep (f), library (0) { + file = f; + + library = shl_load (file.c_str (), BIND_IMMEDIATE, 0L); + + if (! library) + { + using namespace std; + (*current_liboctave_error_handler) ("%s", strerror (errno)); + } } octave_shl_load_shlib::~octave_shl_load_shlib (void) { - close (); -} - -void -octave_shl_load_shlib::open (const std::string& f) -{ - if (! is_open ()) - { - file = f; - - library = shl_load (file.c_str (), BIND_IMMEDIATE, 0L); - - if (library) - stamp_time (); - else - { - using namespace std; - (*current_liboctave_error_handler) ("%s", strerror (errno)); - } - } - else - (*current_liboctave_error_handler) - ("shared library %s is already open", file.c_str ()); + if (library) + shl_unload (library); } void * @@ -386,9 +296,6 @@ int status = shl_findsym (&library, sym_name.c_str (), TYPE_UNDEFINED, &function); - - if (status == 0) - add_to_fcn_names (name); } else (*current_liboctave_error_handler) @@ -397,38 +304,18 @@ return function; } -void -octave_shl_load_shlib::close (octave_shlib::close_hook cl_hook) -{ - if (is_open ()) - { - if (cl_hook) - do_close_hook (cl_hook); - - shl_unload (library); - - library = 0; - - tabula_rasa (); - } -} - #elif defined (HAVE_LOADLIBRARY_API) class -octave_w32_shlib: public octave_base_shlib +octave_w32_shlib: public octave_shlib::shlib_rep { public: - octave_w32_shlib (void); + octave_w32_shlib (const std::string& f); ~octave_w32_shlib (void); - void open (const std::string& f); - - void *search (const std::string& name, name_mangler mangler = 0); - - void close (octave_shlib::close_hook cl_hook = 0); + void *search (const std::string& name, octave_shlib::name_mangler mangler = 0); bool is_open (void) const { return (handle != 0); } @@ -443,57 +330,43 @@ HINSTANCE handle; }; -octave_w32_shlib::octave_w32_shlib (void) - : octave_base_shlib (), handle (0) +octave_w32_shlib::octave_w32_shlib (const std::string& f) + : octave_shlib::shlib_rep (f), handle (0) { + handle = LoadLibrary (file.c_str ()); + + if (! handle) + { + DWORD lastError = GetLastError (); + char *msg; + + switch (lastError) + { + case ERROR_MOD_NOT_FOUND: + case ERROR_DLL_NOT_FOUND: + msg = "could not find library or dependents"; + break; + + case ERROR_INVALID_DLL: + msg = "library or its dependents are damaged"; + break; + + case ERROR_DLL_INIT_FAILED: + msg = "library initialization routine failed"; + break; + + default: + msg = "library open failed"; + } + + (*current_liboctave_error_handler) ("%s: %s", msg, file.c_str ()); + } } octave_w32_shlib::~octave_w32_shlib (void) { - close (); -} - -void -octave_w32_shlib::open (const std::string& f) -{ - if (! is_open ()) - { - file = f; - - handle = LoadLibrary (file.c_str ()); - - if (handle) - stamp_time (); - else - { - DWORD lastError = GetLastError (); - char *msg; - - switch (lastError) - { - case ERROR_MOD_NOT_FOUND: - case ERROR_DLL_NOT_FOUND: - msg = "could not find library or dependents"; - break; - - case ERROR_INVALID_DLL: - msg = "library or its dependents are damaged"; - break; - - case ERROR_DLL_INIT_FAILED: - msg = "library initialization routine failed"; - break; - - default: - msg = "library open failed"; - } - - (*current_liboctave_error_handler) ("%s: %s", msg, file.c_str ()); - } - } - else - (*current_liboctave_error_handler) - ("shared library %s is already open", file.c_str ()); + if (handle) + FreeLibrary (handle); } extern "C" @@ -515,9 +388,6 @@ sym_name = mangler (name); function = octave_w32_library_search (handle, sym_name.c_str ()); - - if (function) - add_to_fcn_names (name); } else (*current_liboctave_error_handler) @@ -526,26 +396,10 @@ return function; } -void -octave_w32_shlib::close (octave_shlib::close_hook cl_hook) -{ - if (is_open ()) - { - if (cl_hook) - do_close_hook (cl_hook); - - FreeLibrary (handle); - - handle = 0; - - tabula_rasa (); - } -} - #elif defined (HAVE_DYLD_API) class -octave_dyld_shlib : public octave_base_shlib +octave_dyld_shlib : public octave_shlib::shlib_rep { public: @@ -555,11 +409,11 @@ void open (const std::string& f); - void *search (const std::string& name, name_mangler mangler = 0); + void *search (const std::string& name, octave_shlib::name_mangler mangler = 0); void close (octave_shlib::close_hook cl_hook = 0); - bool is_open (void) const {return (isOpen); } + bool is_open (void) const {return (handle != 0); } private: @@ -569,70 +423,52 @@ octave_dyld_shlib& operator = (const octave_dyld_shlib&); - bool isOpen; NSObjectFileImage img; NSModule handle; }; -octave_dyld_shlib::octave_dyld_shlib (void) - : octave_base_shlib (), isOpen (false), handle (0) +octave_dyld_shlib::octave_dyld_shlib (const std::string& f) + : octave_shlib::shlib_rep (f), handle (0) { + int returnCode = NSCreateObjectFileImageFromFile (file.c_str (), &img); + + if (NSObjectFileImageSuccess == returnCode) + { + handle = NSLinkModule (img, file.c_str (), + (NSLINKMODULE_OPTION_RETURN_ON_ERROR + | NSLINKMODULE_OPTION_PRIVATE)); + if (! handle) + { + NSLinkEditErrors ler; + int lerno; + const char *file2; + const char *errstr = 0; + + NSLinkEditError (&ler, &lerno, &file2, &errstr); + + if (! errstr) + errstr = "unspecified error"; + + (*current_liboctave_error_handler) + ("%s: %s", file.c_str (), errstr); + } + } + else + { + (*current_liboctave_error_handler) + ("got NSObjectFileImageReturnCode %d", returnCode); + + // FIXME -- should use NSLinkEditError () to get + // more info on what went wrong. + } } octave_dyld_shlib::~octave_dyld_shlib (void) { - close (); -} - -void -octave_dyld_shlib::open (const std::string& f) -{ - int returnCode; - - if (! is_open ()) - { - file = f; - - returnCode = NSCreateObjectFileImageFromFile (file.c_str (), &img); + if (handle) + NSUnLinkModule (handle, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); - if (NSObjectFileImageSuccess == returnCode) - { - handle = NSLinkModule (img, file.c_str (), - (NSLINKMODULE_OPTION_RETURN_ON_ERROR - | NSLINKMODULE_OPTION_PRIVATE)); - if (handle) - { - stamp_time (); - isOpen = true; - } - else - { - NSLinkEditErrors ler; - int lerno; - const char *file2; - const char *errstr = 0; - - NSLinkEditError (&ler, &lerno, &file2, &errstr); - - if (errstr) - (*current_liboctave_error_handler) - ("%s: %s", file.c_str (), errstr); - } - } - else - { - (*current_liboctave_error_handler) - ("got NSObjectFileImageReturnCode %d", returnCode); - - // FIXME -- should use NSLinkEditError () to get - // more info on what went wrong. - } - } - else - { - (*current_liboctave_error_handler) - ("bundle %s is already open", file.c_str ()); - } + NSDestroyObjectFileImage (img); } void * @@ -653,7 +489,6 @@ if (symbol) { function = NSAddressOfSymbol (symbol); - add_to_fcn_names (name); } } else @@ -663,39 +498,23 @@ return function; } -void -octave_dyld_shlib::close (octave_shlib::close_hook cl_hook) -{ - if (is_open ()) - { - do_close_hook (cl_hook); - - NSUnLinkModule (handle, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); - - handle = 0; - - if (NSDestroyObjectFileImage (img)) - isOpen = false; - - tabula_rasa (); - } -} - #endif -octave_shlib * -octave_shlib::make_shlib (void) +octave_shlib::shlib_rep * +octave_shlib::shlib_rep::new_instance (const std::string& f) { #if defined (HAVE_DLOPEN_API) - return new octave_dlopen_shlib (); + return new octave_dlopen_shlib (f); #elif defined (HAVE_SHL_LOAD_API) - return new octave_shl_load_shlib (); + return new octave_shl_load_shlib (f); #elif defined (HAVE_LOADLIBRARY_API) - return new octave_w32_shlib (); + return new octave_w32_shlib (f); #elif defined (HAVE_DYLD_API) - return new octave_dyld_shlib (); + return new octave_dyld_shlib (f); #else - return new octave_base_shlib (); + (*current_liboctave_error_handler) + ("no API for dynamic loading is available"); + return new shlib_rep (); #endif } diff -r 59ed11557715 -r 80432f0ee895 liboctave/oct-shlib.h --- a/liboctave/oct-shlib.h Thu Dec 10 02:09:53 2009 -0500 +++ b/liboctave/oct-shlib.h Thu Dec 10 09:14:47 2009 +0100 @@ -1,6 +1,7 @@ /* Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006, 2007, 2008 John W. Eaton +Copyright (C) 2009 VZLU Prague This file is part of Octave. @@ -24,43 +25,103 @@ #define octave_shlib_h 1 #include +#include #include "oct-time.h" -// This just provides a way to avoid infinite recursion when building -// octave_shlib objects. - -class -OCTAVE_API -octave_xshlib -{ -public: - - octave_xshlib (void) { } -}; - class OCTAVE_API octave_shlib { -public: +public: // FIXME: make this class private? typedef std::string (*name_mangler) (const std::string&); - typedef void (*close_hook) (const std::string&); - octave_shlib (void) : relative (false), rep (make_shlib ()) { } + class shlib_rep + { + public: + + shlib_rep (void) + : count (1), file (), tm_loaded (time_t ()) { } + + protected: + + shlib_rep (const std::string& f); + + public: + + virtual ~shlib_rep (void) + { + instances.erase (file); + } - octave_shlib (const std::string& f) - : relative (false), rep (make_shlib ()) { open (f); } + virtual bool is_open (void) const + { return false; } + + virtual void *search (const std::string&, name_mangler = 0) + { return 0; } + + bool is_out_of_date (void) const; + + // This method will be overriden conditionally. + static shlib_rep *new_instance (const std::string& f); + + static shlib_rep *get_instance (const std::string& f, bool fake); + + octave_time time_loaded (void) const + { return tm_loaded; } + + std::string file_name (void) const + { return file; } + + void insert_hook_name (const std::string& name) const; + + void erase_hook_name (const std::string& name) const; - virtual ~octave_shlib (void) + size_t num_fcn_names (void) const { return fcn_names.size (); } + + void add_fcn_name (const std::string&); + + bool remove_fcn_name (const std::string&); + + void do_close_hook (close_hook cl_hook); + + public: + + int count; + + protected: + + void fake_reload (void); + + std::string file; + octave_time tm_loaded; + + // Set of hooked function names. + typedef std::map::iterator fcn_names_iterator; + typedef std::map::const_iterator fcn_names_const_iterator; + + std::map fcn_names; + + static std::map instances; + }; + +private: + + static shlib_rep nil_rep; + +public: + + octave_shlib (void) : rep (&nil_rep) { rep->count++; } + + octave_shlib (const std::string& f, bool fake = true) + : rep (shlib_rep::get_instance (f, fake)) { } + + ~octave_shlib (void) { - if (rep && --rep->count == 0) - { - delete rep; - rep = 0; - } + if (--rep->count == 0) + delete rep; } octave_shlib (const octave_shlib& sl) @@ -86,51 +147,49 @@ bool operator == (const octave_shlib& sl) const { return (rep == sl.rep); } - operator bool () const { return is_open (); } + operator bool () const { return rep->is_open (); } + + void open (const std::string& f) + { *this = octave_shlib (f); } - virtual void open (const std::string& f) { rep->open (f); } + void close (close_hook cl_hook = 0) + { + if (cl_hook) + rep->do_close_hook (cl_hook); - virtual void *search (const std::string& nm, name_mangler mangler = 0) - { return rep->search (nm, mangler); } + *this = octave_shlib (); + } - virtual void close (close_hook cl_hook = 0) - { rep->close (cl_hook); } + void *search (const std::string& nm, name_mangler mangler = 0) const + { + void *f = rep->search (nm, mangler); + if (f) + rep->add_fcn_name (nm); + + return f; + } - virtual bool remove (const std::string& fcn_name) - { return rep->remove (fcn_name); } + void add (const std::string& name) + { rep->add_fcn_name (name); } - virtual bool is_out_of_date (void) const + bool remove (const std::string& name) + { return rep->remove_fcn_name (name); } + + size_t number_of_functions_loaded (void) const + { return rep->num_fcn_names (); } + + bool is_out_of_date (void) const { return rep->is_out_of_date (); } - void mark_relative (void) { relative = true; } - - bool is_relative (void) const { return relative; } - - virtual size_t number_of_functions_loaded (void) const - { return rep->number_of_functions_loaded (); } - - virtual std::string file_name (void) const + std::string file_name (void) const { return rep->file_name (); } - virtual octave_time time_loaded (void) const + octave_time time_loaded (void) const { return rep->time_loaded (); } -protected: - - octave_shlib (const octave_xshlib&) : rep (0) { } - - virtual bool is_open (void) const { return rep->is_open (); } - - static octave_shlib *make_shlib (void); +private: - // TRUE if this function was found from a relative path element. - bool relative; - - union - { - octave_shlib *rep; - int count; - }; + shlib_rep *rep; }; #endif diff -r 59ed11557715 -r 80432f0ee895 src/ChangeLog --- a/src/ChangeLog Thu Dec 10 02:09:53 2009 -0500 +++ b/src/ChangeLog Thu Dec 10 09:14:47 2009 +0100 @@ -1,3 +1,14 @@ +2009-12-09 Jaroslav Hajek + + * symtab.h (symbol_table::fcn_info::clear_autoload_function): New method. + (symbol_table::clear_dld_function): New method. + * dynamic-ld.cc (octave_shlib_list::do_remove): Switch order of stmts. + (octave_mex_file_list::do_remove): Likewise. + (do_clear_function): Call symbol_table::clear_dld_function. + (octave_dynamic_loader::do_load_oct): Don't use + octave_shlib::mark_relative. + (octave_dynamic_loader::do_load_mex): Ditto. + 2009-12-10 John W. Eaton * file-io.cc (fopen_mode_to_ios_mode): Allow "+" at the end of diff -r 59ed11557715 -r 80432f0ee895 src/dynamic-ld.cc --- a/src/dynamic-ld.cc Thu Dec 10 02:09:53 2009 -0500 +++ b/src/dynamic-ld.cc Thu Dec 10 09:14:47 2009 +0100 @@ -107,9 +107,11 @@ { if (*p == shl) { - shl.close (cl_hook); + // Erase first to avoid potentially invalidating the pointer by the + // following hooks. + lib_list.erase (p); - lib_list.erase (p); + shl.close (cl_hook); break; } @@ -240,9 +242,11 @@ { if (*p == shl) { - shl.close (cl_hook); + // Erase first to avoid potentially invalidating the pointer by the + // following hooks. + file_list.erase (p); - file_list.erase (p); + shl.close (cl_hook); break; } @@ -309,7 +313,7 @@ { warning_with_id ("Octave:reload-forces-clear", " %s", fcn_name.c_str ()); - symbol_table::clear_user_function (fcn_name); + symbol_table::clear_dld_function (fcn_name); } static void @@ -346,12 +350,7 @@ oct_file.open (file_name); if (! error_state && oct_file) - { - octave_shlib_list::append (oct_file); - - if (relative) - oct_file.mark_relative (); - } + octave_shlib_list::append (oct_file); } if (! error_state) @@ -413,12 +412,7 @@ mex_file.open (file_name); if (! error_state && mex_file) - { - octave_shlib_list::append (mex_file); - - if (relative) - mex_file.mark_relative (); - } + octave_shlib_list::append (mex_file); } if (! error_state) diff -r 59ed11557715 -r 80432f0ee895 src/symtab.h --- a/src/symtab.h Thu Dec 10 02:09:53 2009 -0500 +++ b/src/symtab.h Thu Dec 10 09:14:47 2009 +0100 @@ -847,6 +847,8 @@ void clear_user_function (void) { rep->clear_user_function (); } + void clear_autoload_function (void) { rep->clear_autoload_function (); } + void clear_mex_function (void) { rep->clear_mex_function (); } void add_dispatch (const std::string& type, const std::string& fname) @@ -1392,6 +1394,20 @@ // error ("clear: no such function `%s'", name.c_str ()); } + // This clears oct and mex files, incl. autoloads. + static void clear_dld_function (const std::string& name) + { + fcn_table_iterator p = fcn_table.find (name); + + if (p != fcn_table.end ()) + { + fcn_info& finfo = p->second; + + finfo.clear_autoload_function (); + finfo.clear_user_function (); + } + } + static void clear_mex_functions (void) { for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)