aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lane.cpp42
-rw-r--r--src/lane.h9
2 files changed, 28 insertions, 23 deletions
diff --git a/src/lane.cpp b/src/lane.cpp
index d6c9960..10060ad 100644
--- a/src/lane.cpp
+++ b/src/lane.cpp
@@ -499,7 +499,7 @@ namespace {
499// xxh64 of string "kStackTraceRegKey" generated at https://www.pelock.com/products/hash-calculator 499// xxh64 of string "kStackTraceRegKey" generated at https://www.pelock.com/products/hash-calculator
500static constexpr RegistryUniqueKey kStackTraceRegKey{ 0x3F327747CACAA904ull }; 500static constexpr RegistryUniqueKey kStackTraceRegKey{ 0x3F327747CACAA904ull };
501 501
502[[nodiscard]] static int lane_error(lua_State* L_) 502int Lane::LuaErrorHandler(lua_State* L_)
503{ 503{
504 // error message (any type) 504 // error message (any type)
505 STACK_CHECK_START_ABS(L_, 1); // L_: some_error 505 STACK_CHECK_START_ABS(L_, 1); // L_: some_error
@@ -510,7 +510,7 @@ static constexpr RegistryUniqueKey kStackTraceRegKey{ 0x3F327747CACAA904ull };
510 return 1; // just pass on 510 return 1; // just pass on
511 } 511 }
512 512
513 STACK_GROW(L_, 3); 513 STACK_GROW(L_, 4); // lua_setfield consumes a stack slot, so we have to account for it
514 bool const _extended{ kExtendedStackTraceRegKey.readBoolValue(L_) }; 514 bool const _extended{ kExtendedStackTraceRegKey.readBoolValue(L_) };
515 STACK_CHECK(L_, 1); 515 STACK_CHECK(L_, 1);
516 516
@@ -537,19 +537,19 @@ static constexpr RegistryUniqueKey kStackTraceRegKey{ 0x3F327747CACAA904ull };
537 lua_newtable(L_); // L_: some_error {} {} 537 lua_newtable(L_); // L_: some_error {} {}
538 538
539 lua_pushstring(L_, _ar.source); // L_: some_error {} {} source 539 lua_pushstring(L_, _ar.source); // L_: some_error {} {} source
540 lua_setfield(L_, -2, "source"); // L_: some_error {} {} 540 luaG_setfield(L_, -2, std::string_view{ "source" }); // L_: some_error {} {}
541 541
542 lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline 542 lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline
543 lua_setfield(L_, -2, "currentline"); // L_: some_error {} {} 543 luaG_setfield(L_, -2, std::string_view{ "currentline" }); // L_: some_error {} {}
544 544
545 lua_pushstring(L_, _ar.name); // L_: some_error {} {} name 545 lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name
546 lua_setfield(L_, -2, "name"); // L_: some_error {} {} 546 luaG_setfield(L_, -2, std::string_view{ "name" }); // L_: some_error {} {}
547 547
548 lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat 548 lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat
549 lua_setfield(L_, -2, "namewhat"); // L_: some_error {} {} 549 luaG_setfield(L_, -2, std::string_view{ "namewhat" }); // L_: some_error {} {}
550 550
551 lua_pushstring(L_, _ar.what); // L_: some_error {} {} what 551 lua_pushstring(L_, _ar.what); // L_: some_error {} {} what
552 lua_setfield(L_, -2, "what"); // L_: some_error {} {} 552 luaG_setfield(L_, -2, std::string_view{ "what" }); // L_: some_error {} {}
553 } else if (_ar.currentline > 0) { 553 } else if (_ar.currentline > 0) {
554 luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" 554 luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah"
555 } else { 555 } else {
@@ -630,7 +630,7 @@ static void push_stack_trace(lua_State* L_, Lane::ErrorTraceLevel errorTraceLeve
630 STACK_GROW(L_, 5); 630 STACK_GROW(L_, 5);
631 631
632 int const _finalizers_index{ lua_gettop(L_) }; 632 int const _finalizers_index{ lua_gettop(L_) };
633 int const _err_handler_index{ (errorTraceLevel_ != Lane::Minimal) ? (lua_pushcfunction(L_, lane_error), lua_gettop(L_)) : 0 }; 633 int const _err_handler_index{ (errorTraceLevel_ != Lane::Minimal) ? (lua_pushcfunction(L_, Lane::LuaErrorHandler), lua_gettop(L_)) : 0 };
634 634
635 LuaError _rc{ LuaError::OK }; 635 LuaError _rc{ LuaError::OK };
636 for (int _n = static_cast<int>(lua_rawlen(L_, _finalizers_index)); _n > 0; --_n) { 636 for (int _n = static_cast<int>(lua_rawlen(L_, _finalizers_index)); _n > 0; --_n) {
@@ -763,7 +763,7 @@ static void lane_main(Lane* const lane_)
763 LuaError _rc{ LuaError::ERRRUN }; 763 LuaError _rc{ LuaError::ERRRUN };
764 if (lane_->status == Lane::Pending) { // nothing wrong happened during preparation, we can work 764 if (lane_->status == Lane::Pending) { // nothing wrong happened during preparation, we can work
765 // At this point, the lane function and arguments are on the stack, possibly preceded by the error handler 765 // At this point, the lane function and arguments are on the stack, possibly preceded by the error handler
766 int const _errorHandlerCount{ lane_->errorTraceLevel == Lane::Minimal ? 0 : 1}; 766 int const _errorHandlerCount{ lane_->errorHandlerCount() };
767 int _nargs{ lua_gettop(_L) - 1 - _errorHandlerCount }; 767 int _nargs{ lua_gettop(_L) - 1 - _errorHandlerCount };
768 { 768 {
769 std::unique_lock _guard{ lane_->doneMutex }; 769 std::unique_lock _guard{ lane_->doneMutex };
@@ -777,7 +777,7 @@ static void lane_main(Lane* const lane_)
777 // S and L are different: we run as a coroutine in Lua thread L created in state S 777 // S and L are different: we run as a coroutine in Lua thread L created in state S
778 do { 778 do {
779 int _nresults{}; 779 int _nresults{};
780 _rc = luaG_resume(_L, nullptr, _nargs, &_nresults); // L: eh? retvals|err 780 _rc = luaG_resume(_L, nullptr, _nargs, &_nresults); // L: eh? retvals|err...
781 if (_rc == LuaError::YIELD) { 781 if (_rc == LuaError::YIELD) {
782 // change our status to suspended, and wait until someone wants us to resume 782 // change our status to suspended, and wait until someone wants us to resume
783 std::unique_lock _guard{ lane_->doneMutex }; 783 std::unique_lock _guard{ lane_->doneMutex };
@@ -794,6 +794,15 @@ static void lane_main(Lane* const lane_)
794 _nargs = lua_gettop(_L); 794 _nargs = lua_gettop(_L);
795 } 795 }
796 } while (_rc == LuaError::YIELD); 796 } while (_rc == LuaError::YIELD);
797 if (_rc != LuaError::OK) { // : err...
798 // for some reason, in my tests with Lua 5.4, when the coroutine raises an error, I have 3 copies of it on the stack
799 // or false + the error message when running Lua 5.1
800 // since the rest of our code wants only the error message, let us keep only the latter.
801 lua_replace(_L, 1); // L: err...
802 lua_settop(_L, 1); // L: err
803 // now we build the stack trace table if the error trace level requests it
804 std::ignore = Lane::LuaErrorHandler(_L); // L: err
805 }
797 } 806 }
798 807
799 if (_errorHandlerCount) { 808 if (_errorHandlerCount) {
@@ -1098,17 +1107,6 @@ void Lane::PushMetatable(lua_State* L_)
1098 1107
1099// ################################################################################################# 1108// #################################################################################################
1100 1109
1101[[nodiscard]] int Lane::pushErrorHandler() const
1102{
1103 if (errorTraceLevel != ErrorTraceLevel::Minimal) {
1104 lua_pushcfunction(L, lane_error);
1105 return 1;
1106 }
1107 return 0;
1108}
1109
1110// #################################################################################################
1111
1112void Lane::pushStatusString(lua_State* L_) const 1110void Lane::pushStatusString(lua_State* L_) const
1113{ 1111{
1114 std::string_view const _str{ threadStatusString() }; 1112 std::string_view const _str{ threadStatusString() };
diff --git a/src/lane.h b/src/lane.h
index 6dccd3a..f0fd0ac 100644
--- a/src/lane.h
+++ b/src/lane.h
@@ -158,12 +158,19 @@ class Lane
158 lua_close(_L); // this collects our coroutine thread at the same time 158 lua_close(_L); // this collects our coroutine thread at the same time
159 } 159 }
160 [[nodiscard]] std::string_view errorTraceLevelString() const; 160 [[nodiscard]] std::string_view errorTraceLevelString() const;
161 [[nodiscard]] int errorHandlerCount() const noexcept
162 {
163 // don't push a error handler when in coroutine mode, as the first lua_resume wants only the function and its arguments on the stack
164 return ((errorTraceLevel == Lane::Minimal) || isCoroutine()) ? 0 : 1;
165 }
166 [[nodiscard]] bool isCoroutine() const noexcept { return S != L; }
161 [[nodiscard]] std::string_view getDebugName() const 167 [[nodiscard]] std::string_view getDebugName() const
162 { 168 {
163 std::lock_guard<std::mutex> _guard{ debugNameMutex }; 169 std::lock_guard<std::mutex> _guard{ debugNameMutex };
164 return debugName; 170 return debugName;
165 } 171 }
166 [[nodiscard]] int pushErrorHandler() const; 172 static int LuaErrorHandler(lua_State* L_);
173 [[nodiscard]] int pushErrorHandler() const noexcept { return (errorHandlerCount() == 0) ? 0 : (lua_pushcfunction(L, LuaErrorHandler), 1); }
167 [[nodiscard]] std::string_view pushErrorTraceLevel(lua_State* L_) const; 174 [[nodiscard]] std::string_view pushErrorTraceLevel(lua_State* L_) const;
168 static void PushMetatable(lua_State* L_); 175 static void PushMetatable(lua_State* L_);
169 void pushStatusString(lua_State* L_) const; 176 void pushStatusString(lua_State* L_) const;