aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/keeper.cpp9
-rw-r--r--src/keeper.hpp2
-rw-r--r--src/lane.cpp12
-rw-r--r--src/universe.cpp12
4 files changed, 23 insertions, 12 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp
index c8c470f..ca2a80d 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -952,15 +952,15 @@ void Keepers::collectGarbage()
952// ################################################################################################# 952// #################################################################################################
953 953
954 954
955void Keepers::close() 955bool Keepers::close()
956{ 956{
957 if (isClosing.test_and_set(std::memory_order_release)) { 957 if (isClosing.test_and_set(std::memory_order_release)) {
958 assert(false); // should never close more than once in practice 958 return false; // should never close more than once in practice
959 return;
960 } 959 }
961 960
961 // We may have not initialized the keepers if an error was raised in Universe::Create because of bad settings
962 if (std::holds_alternative<std::monostate>(keeper_array)) { 962 if (std::holds_alternative<std::monostate>(keeper_array)) {
963 return; 963 return true;
964 } 964 }
965 965
966 auto _closeOneKeeper = [](Keeper& keeper_) { 966 auto _closeOneKeeper = [](Keeper& keeper_) {
@@ -989,6 +989,7 @@ void Keepers::close()
989 } 989 }
990 990
991 keeper_array.emplace<std::monostate>(); 991 keeper_array.emplace<std::monostate>();
992 return true;
992} 993}
993 994
994// ################################################################################################# 995// #################################################################################################
diff --git a/src/keeper.hpp b/src/keeper.hpp
index f1083b3..0aa44f2 100644
--- a/src/keeper.hpp
+++ b/src/keeper.hpp
@@ -68,7 +68,7 @@ struct Keepers
68 68
69 Keepers() = default; 69 Keepers() = default;
70 void collectGarbage(); 70 void collectGarbage();
71 void close(); 71 bool close();
72 [[nodiscard]] 72 [[nodiscard]]
73 Keeper* getKeeper(KeeperIndex idx_); 73 Keeper* getKeeper(KeeperIndex idx_);
74 [[nodiscard]] 74 [[nodiscard]]
diff --git a/src/lane.cpp b/src/lane.cpp
index 5cebdfa..e6ea2e5 100644
--- a/src/lane.cpp
+++ b/src/lane.cpp
@@ -783,10 +783,14 @@ static void lane_main(Lane* const lane_)
783 if (lane_->selfdestructRemove()) { // check and remove (under lock!) 783 if (lane_->selfdestructRemove()) { // check and remove (under lock!)
784 // We're a free-running thread and no-one is there to clean us up. 784 // We're a free-running thread and no-one is there to clean us up.
785 lane_->closeState(); 785 lane_->closeState();
786 lane_->U->selfdestructMutex.lock(); 786
787 // done with lua_close(), terminal shutdown sequence may proceed 787 // let's try not to crash if the lane didn't terminate gracefully and the Universe met its end
788 lane_->U->selfdestructingCount.fetch_sub(1, std::memory_order_release); 788 if (!lane_->flaggedAfterUniverseGC.load(std::memory_order_relaxed)) {
789 lane_->U->selfdestructMutex.unlock(); 789 lane_->U->selfdestructMutex.lock();
790 // done with lua_close(), terminal shutdown sequence may proceed
791 lane_->U->selfdestructingCount.fetch_sub(1, std::memory_order_release);
792 lane_->U->selfdestructMutex.unlock();
793 }
790 794
791 // we destroy ourselves, therefore our thread member too, from inside the thread body 795 // we destroy ourselves, therefore our thread member too, from inside the thread body
792 // detach so that we don't try to join, as this doesn't seem a good idea 796 // detach so that we don't try to join, as this doesn't seem a good idea
diff --git a/src/universe.cpp b/src/universe.cpp
index 335f056..0f41585 100644
--- a/src/universe.cpp
+++ b/src/universe.cpp
@@ -178,8 +178,8 @@ Universe* Universe::Create(lua_State* const L_)
178 178
179 // Linked chains handling 179 // Linked chains handling
180 _U->selfdestructFirst = SELFDESTRUCT_END; 180 _U->selfdestructFirst = SELFDESTRUCT_END;
181 _U->initializeAllocatorFunction(L_); 181 _U->initializeAllocatorFunction(L_); // this can raise an error
182 _U->initializeOnStateCreate(L_); 182 _U->initializeOnStateCreate(L_); // this can raise an error
183 _U->keepers.initialize(*_U, L_, static_cast<size_t>(_nbUserKeepers), _keepers_gc_threshold); 183 _U->keepers.initialize(*_U, L_, static_cast<size_t>(_nbUserKeepers), _keepers_gc_threshold);
184 STACK_CHECK(L_, 0); 184 STACK_CHECK(L_, 0);
185 185
@@ -463,7 +463,11 @@ int Universe::UniverseGC(lua_State* const L_)
463 // that manifests as a crash inside ntdll!longjmp() function, in optimized builds only 463 // that manifests as a crash inside ntdll!longjmp() function, in optimized builds only
464 lua_error(L_); 464 lua_error(L_);
465 } 465 }
466 } else {
467 // we didn't use the error message, let's keep a clean stack
468 lua_pop(L_, 1); // L_: U
466 } 469 }
470 STACK_CHECK(L_, 1);
467 471
468 // --------------------------------------------------------- 472 // ---------------------------------------------------------
469 // we don't reach that point if some lanes are still running 473 // we don't reach that point if some lanes are still running
@@ -472,7 +476,9 @@ int Universe::UniverseGC(lua_State* const L_)
472 // no need to mutex-protect this as all lanes in the universe are gone at that point 476 // no need to mutex-protect this as all lanes in the universe are gone at that point
473 Linda::DeleteTimerLinda(L_, std::exchange(_U->timerLinda, nullptr), PK); 477 Linda::DeleteTimerLinda(L_, std::exchange(_U->timerLinda, nullptr), PK);
474 478
475 _U->keepers.close(); 479 if (!_U->keepers.close()) {
480 raise_luaL_error(L_, "INTERNAL ERROR: Keepers closed more than once");
481 }
476 482
477 // remove the protected allocator, if any 483 // remove the protected allocator, if any
478 _U->protectedAllocator.removeFrom(L_); 484 _U->protectedAllocator.removeFrom(L_);