From af92d1f8701f7dd47c9d5a87e8c078d64133f70e Mon Sep 17 00:00:00 2001 From: VaclavT Date: Mon, 3 May 2021 18:32:36 +0200 Subject: [PATCH] better (thread) error handling --- ml.cpp | 24 ++++++++++++++++-------- ml.h | 9 +++++++-- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/ml.cpp b/ml.cpp index dcd82f7..0489169 100644 --- a/ml.cpp +++ b/ml.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #define TOO_FEW_ARGS "too few arguments to function" @@ -624,12 +625,16 @@ MlError::~MlError() { delete cause; } -std::string MlError::description() { +std::string MlError::description() const { // return "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + msg + "\""; return MlPerfMon::instance().callstack() + "error: the expression `" + cause->debug() + "` with message \"" + msg + "\""; } +const char* MlError::what() const noexcept { + return ("error: the expression `" + cause->debug() + "` with message \"" + msg + "\"").c_str(); +} + void MlEnvironment::combine(MlEnvironment const &other) { // Normally, I would use the `insert` method of the `map` class, // but it doesn't overwrite previously declared values for keys. @@ -1753,8 +1758,12 @@ namespace builtin { MlValue thread_create(std::vector args, MlEnvironment &env) { auto functor = [](std::vector args, MlEnvironment &env) -> void { - for (size_t i = 0; i < args.size(); i++) - MlValue acc = args[i].eval(env); + try { + for (size_t i = 0; i < args.size(); i++) + MlValue acc = args[i].eval(env); + } catch (std::exception &e) { + std::cerr << "thread exception: " << e.what() << std::endl; + } }; std::thread th(functor, args, std::ref(env)); @@ -1777,9 +1786,7 @@ namespace builtin { if (args[0].as_string() != "ilock") throw MlError(MlValue("thread_under_lock", thread_under_lock), env, UNKNOWN_ERROR); - std::lock_guard lockGuard(interpreter_mutex); - MlValue acc; for (size_t i = 0; i < args.size(); i++) acc = args[i].eval(env); @@ -1791,6 +1798,7 @@ namespace builtin { if (args.size() != 0) throw MlError(MlValue("threads_join", threads_join), env, TOO_MANY_ARGS); + std::lock_guard lockGuard(register_mutex); for (auto &th : threads_register) if (th.joinable()) th.join(); @@ -1841,7 +1849,7 @@ void repl(MlEnvironment &env) { } catch (MlError &e) { std::cerr << e.description() << std::endl; MlPerfMon::instance().clear_callstack(); - } catch (std::runtime_error &e) { + } catch (std::exception &e) { std::cerr << e.what() << std::endl; } } @@ -2065,8 +2073,8 @@ int main(int argc, char *argv[]) { return 0; } catch (MlError &e) { - std::cerr << e.description() << std::endl; - } catch (std::runtime_error &e) { + std::cerr << e.what() << std::endl; + } catch (const std::exception &e) { std::cerr << MlPerfMon::instance().callstack() << e.what() << std::endl; MlPerfMon::instance().clear_callstack(); } diff --git a/ml.h b/ml.h index 7c618fb..ec2fc5d 100644 --- a/ml.h +++ b/ml.h @@ -67,8 +67,10 @@ private: // An exception thrown by the lisp -class MlError { +class MlError : public std::exception { public: + MlError() = delete; + // Create an error with the value that caused the error, // the scope where the error was found, and the message. MlError(const MlValue &v, MlEnvironment const &env, const char *msg); @@ -79,7 +81,10 @@ public: ~MlError(); // Get the printable error description. - std::string description(); + std::string description() const; + + // inherited from std::exception + virtual const char* what() const noexcept; private: MlValue *cause;