# # # patch "cmd_netsync.cc" # from [8bfd914c3727818036e83c65f72cff22cca86222] # to [7fe932e2b28587a6cea8f9380de4ea67ce64e6db] # # patch "monotone.cc" # from [30b9b579faa66edf99d8158a2a86bc31cc397e5a] # to [93efe8898e46a4888eff29a34a77bfedbe7172ce] # # patch "ui.cc" # from [6faee43c3da0f450bd0a41707e96afbe954c5095] # to [c1706a9c8cc139e1489b06515156c1171c0b071d] # # patch "ui.hh" # from [2ad61177a522bbc9fb7dae6d6c90b79e6a3ff639] # to [5c9d5db3978343c279096c8aee2b51f8408feb4d] # ============================================================ --- cmd_netsync.cc 8bfd914c3727818036e83c65f72cff22cca86222 +++ cmd_netsync.cc 7fe932e2b28587a6cea8f9380de4ea67ce64e6db @@ -27,6 +27,7 @@ #include "database.hh" #include "roster.hh" #include "vocab_cast.hh" +#include "ui.hh" #include @@ -293,26 +294,44 @@ public: class dir_cleanup_helper { public: - dir_cleanup_helper(system_path const & new_dir, bool i_db) : - commited(false), internal_db(i_db), dir(new_dir) {} + dir_cleanup_helper(system_path const & new_dir, bool i_db) + : committed(false), internal_db(i_db), dir(new_dir) + {} ~dir_cleanup_helper() { - if (!commited && directory_exists(dir)) + if (!committed && directory_exists(dir)) { -#ifdef WIN32 + // Don't need to worry about where the db is on Unix. +#ifndef WIN32 + internal_db = false; +#endif + + // This is probably happening in the middle of another exception. + // Do not let anything that delete_dir_recursive throws escape, or + // the runtime will call std::terminate... if (!internal_db) - delete_dir_recursive(dir); -#else - delete_dir_recursive(dir); -#endif /* WIN32 */ + { + try + { + delete_dir_recursive(dir); + } + catch (std::exception const & ex) + { + ui.fatal_exception(ex); + } + catch (...) + { + ui.fatal_exception(); + } + } } } void commit(void) { - commited = true; + committed = true; } private: - bool commited; + bool committed; bool internal_db; system_path dir; }; ============================================================ --- monotone.cc 30b9b579faa66edf99d8158a2a86bc31cc397e5a +++ monotone.cc 93efe8898e46a4888eff29a34a77bfedbe7172ce @@ -294,43 +294,13 @@ cpp_main(int argc, char ** argv) return app.opts.help ? 0 : 2; } } - catch (option::option_error const & inf) - { - ui.inform(inf.what()); - return 1; - } - catch (recoverable_failure & inf) - { - ui.inform(inf.what()); - return 1; - } - catch (unrecoverable_failure & inf) - { - if (inf.caused_by() == origin::database) - ui.fatal_db(inf.what()); - else - ui.fatal(inf.what()); - return 3; - } - catch (ios_base::failure const & ex) - { - // an error has already been printed - return 1; - } - catch (std::bad_alloc) - { - ui.inform(_("error: memory exhausted")); - return 1; - } catch (std::exception const & ex) { - ui.fatal_exception (ex); - return 3; + return ui.fatal_exception(ex); } catch (...) { - ui.fatal_exception (); - return 3; + return ui.fatal_exception(); } // control cannot reach this point ============================================================ --- ui.cc 6faee43c3da0f450bd0a41707e96afbe954c5095 +++ ui.cc c1706a9c8cc139e1489b06515156c1171c0b071d @@ -555,51 +555,83 @@ user_interface::fatal_db(string const & // Report what we can about a fatal exception (caught in the outermost catch // handlers) which is from the std::exception hierarchy. In this case we -// can access the exception object. -void +// can access the exception object, and we can try to figure out what it +// really is by typeinfo operations. +int user_interface::fatal_exception(std::exception const & ex) { - using std::strcmp; - using std::strncmp; - char const * ex_name = typeid(ex).name(); - char const * ex_dem = demangle_typename(ex_name); - char const * ex_what = ex.what(); + char const * what = ex.what(); + unrecoverable_failure const * inf; - if (ex_dem == 0) - ex_dem = ex_name; + if (dynamic_cast(&ex) + || dynamic_cast(&ex)) + { + this->inform(what); + return 1; + } + else if ((inf = dynamic_cast(&ex))) + { + if (inf->caused_by() == origin::database) + this->fatal_db(what); + else + this->fatal(what); + return 3; + } + else if (dynamic_cast(&ex)) + { + // an error has already been printed + return 1; + } + else if (dynamic_cast(&ex)) + { + this->inform(_("error: memory exhausted")); + return 1; + } + else // we can at least produce the class name and the what()... + { + using std::strcmp; + using std::strncmp; + char const * name = typeid(ex).name(); + char const * dem = demangle_typename(name); - // some demanglers stick "class" at the beginning of their output, - // which looks dumb in this context - if (!strncmp(ex_dem, "class ", 6)) - ex_dem += 6; + if (dem == 0) + dem = name; - // only print what() if it's interesting, i.e. nonempty and different - // from the name (mangled or otherwise) of the exception type. - if (ex_what == 0 || ex_what[0] == 0 - || !strcmp(ex_what, ex_name) - || !strcmp(ex_what, ex_dem)) - this->fatal(ex_dem); - else - this->fatal(i18n_format("%s: %s") % ex_dem % ex_what); + // some demanglers stick "class" at the beginning of their output, + // which looks dumb in this context + if (!strncmp(dem, "class ", 6)) + dem += 6; + + // only print what() if it's interesting, i.e. nonempty and different + // from the name (mangled or otherwise) of the exception type. + if (what == 0 || what[0] == 0 + || !strcmp(what, name) + || !strcmp(what, dem)) + this->fatal(dem); + else + this->fatal(i18n_format("%s: %s") % dem % what); + return 3; + } } // Report what we can about a fatal exception (caught in the outermost catch // handlers) which is of unknown type. If we have the interfaces, // we can at least get the type_info object. -void +int user_interface::fatal_exception() { - std::type_info *ex_type = get_current_exception_type(); - if (ex_type) + std::type_info *type = get_current_exception_type(); + if (type) { - char const * ex_name = ex_type->name(); - char const * ex_dem = demangle_typename(ex_name); - if (ex_dem == 0) - ex_dem = ex_name; - this->fatal(ex_dem); + char const * name = type->name(); + char const * dem = demangle_typename(name); + if (dem == 0) + dem = name; + this->fatal(dem); } else - this->fatal("exception of unknown type"); + this->fatal(_("C++ exception of unknown type")); + return 3; } string ============================================================ --- ui.hh 2ad61177a522bbc9fb7dae6d6c90b79e6a3ff639 +++ ui.hh 5c9d5db3978343c279096c8aee2b51f8408feb4d @@ -60,8 +60,8 @@ public: void inform(std::string const & line); void inform(format_base const & fmt) { inform(fmt.str()); } void inform_usage(usage const & u, options & opts); - void fatal_exception(std::exception const & ex); - void fatal_exception(); + int fatal_exception(std::exception const & ex); + int fatal_exception(); void set_tick_trailer(std::string const & trailer); void set_tick_write_dot(); void set_tick_write_count();