better (thread) error handling

This commit is contained in:
VaclavT 2021-05-03 18:32:36 +02:00
parent c17d43724a
commit af92d1f870
2 changed files with 23 additions and 10 deletions

24
ml.cpp
View File

@ -22,6 +22,7 @@
#include <ctime> #include <ctime>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <mutex>
#define TOO_FEW_ARGS "too few arguments to function" #define TOO_FEW_ARGS "too few arguments to function"
@ -624,12 +625,16 @@ MlError::~MlError() {
delete cause; 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 "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + msg + "\"";
return MlPerfMon::instance().callstack() + return MlPerfMon::instance().callstack() +
"error: the expression `" + cause->debug() + "` with message \"" + msg + "\""; "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) { void MlEnvironment::combine(MlEnvironment const &other) {
// Normally, I would use the `insert` method of the `map` class, // Normally, I would use the `insert` method of the `map` class,
// but it doesn't overwrite previously declared values for keys. // but it doesn't overwrite previously declared values for keys.
@ -1753,8 +1758,12 @@ namespace builtin {
MlValue thread_create(std::vector<MlValue> args, MlEnvironment &env) { MlValue thread_create(std::vector<MlValue> args, MlEnvironment &env) {
auto functor = [](std::vector<MlValue> args, MlEnvironment &env) -> void { auto functor = [](std::vector<MlValue> args, MlEnvironment &env) -> void {
for (size_t i = 0; i < args.size(); i++) try {
MlValue acc = args[i].eval(env); 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)); std::thread th(functor, args, std::ref(env));
@ -1777,9 +1786,7 @@ namespace builtin {
if (args[0].as_string() != "ilock") if (args[0].as_string() != "ilock")
throw MlError(MlValue("thread_under_lock", thread_under_lock), env, UNKNOWN_ERROR); throw MlError(MlValue("thread_under_lock", thread_under_lock), env, UNKNOWN_ERROR);
std::lock_guard<std::mutex> lockGuard(interpreter_mutex); std::lock_guard<std::mutex> lockGuard(interpreter_mutex);
MlValue acc; MlValue acc;
for (size_t i = 0; i < args.size(); i++) for (size_t i = 0; i < args.size(); i++)
acc = args[i].eval(env); acc = args[i].eval(env);
@ -1791,6 +1798,7 @@ namespace builtin {
if (args.size() != 0) if (args.size() != 0)
throw MlError(MlValue("threads_join", threads_join), env, TOO_MANY_ARGS); throw MlError(MlValue("threads_join", threads_join), env, TOO_MANY_ARGS);
std::lock_guard<std::mutex> lockGuard(register_mutex);
for (auto &th : threads_register) for (auto &th : threads_register)
if (th.joinable()) th.join(); if (th.joinable()) th.join();
@ -1841,7 +1849,7 @@ void repl(MlEnvironment &env) {
} catch (MlError &e) { } catch (MlError &e) {
std::cerr << e.description() << std::endl; std::cerr << e.description() << std::endl;
MlPerfMon::instance().clear_callstack(); MlPerfMon::instance().clear_callstack();
} catch (std::runtime_error &e) { } catch (std::exception &e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
} }
} }
@ -2065,8 +2073,8 @@ int main(int argc, char *argv[]) {
return 0; return 0;
} catch (MlError &e) { } catch (MlError &e) {
std::cerr << e.description() << std::endl; std::cerr << e.what() << std::endl;
} catch (std::runtime_error &e) { } catch (const std::exception &e) {
std::cerr << MlPerfMon::instance().callstack() << e.what() << std::endl; std::cerr << MlPerfMon::instance().callstack() << e.what() << std::endl;
MlPerfMon::instance().clear_callstack(); MlPerfMon::instance().clear_callstack();
} }

9
ml.h
View File

@ -67,8 +67,10 @@ private:
// An exception thrown by the lisp // An exception thrown by the lisp
class MlError { class MlError : public std::exception {
public: public:
MlError() = delete;
// Create an error with the value that caused the error, // Create an error with the value that caused the error,
// the scope where the error was found, and the message. // the scope where the error was found, and the message.
MlError(const MlValue &v, MlEnvironment const &env, const char *msg); MlError(const MlValue &v, MlEnvironment const &env, const char *msg);
@ -79,7 +81,10 @@ public:
~MlError(); ~MlError();
// Get the printable error description. // Get the printable error description.
std::string description(); std::string description() const;
// inherited from std::exception
virtual const char* what() const noexcept;
private: private:
MlValue *cause; MlValue *cause;