diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/universe.cpp | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/src/universe.cpp b/src/universe.cpp index 06f7f21..3255c7f 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
| @@ -227,9 +227,9 @@ static int luaG_provide_protected_allocator(lua_State* const L_) | |||
| 227 | 227 | ||
| 228 | // ################################################################################################# | 228 | // ################################################################################################# |
| 229 | 229 | ||
| 230 | // already called under protection of selfdestructMutex | ||
| 230 | void Universe::flagDanglingLanes() const | 231 | void Universe::flagDanglingLanes() const |
| 231 | { | 232 | { |
| 232 | std::lock_guard<std::mutex> _guard{ selfdestructMutex }; | ||
| 233 | Lane* _lane{ selfdestructFirst }; | 233 | Lane* _lane{ selfdestructFirst }; |
| 234 | while (_lane != SELFDESTRUCT_END) { | 234 | while (_lane != SELFDESTRUCT_END) { |
| 235 | _lane->flaggedAfterUniverseGC.store(true, std::memory_order_relaxed); | 235 | _lane->flaggedAfterUniverseGC.store(true, std::memory_order_relaxed); |
| @@ -460,22 +460,25 @@ int Universe::UniverseGC(lua_State* const L_) | |||
| 460 | } | 460 | } |
| 461 | STACK_CHECK(L_, 2); | 461 | STACK_CHECK(L_, 2); |
| 462 | 462 | ||
| 463 | // now, all remaining lanes are flagged. if they crash because we remove keepers and the Universe from under them, it is their fault | 463 | { |
| 464 | bool const _detectedUncooperativeLanes{ _U->selfdestructFirst != SELFDESTRUCT_END }; | 464 | std::lock_guard<std::mutex> _guard{ _U->selfdestructMutex }; |
| 465 | if (_detectedUncooperativeLanes) { | 465 | // now, all remaining lanes are flagged. if they crash because we remove keepers and the Universe from under them, it is their fault |
| 466 | _U->flagDanglingLanes(); | 466 | bool const _detectedUncooperativeLanes{ _U->selfdestructFirst != SELFDESTRUCT_END }; |
| 467 | if (luaG_tostring(L_, kIdxTop) == "freeze") { | 467 | if (_detectedUncooperativeLanes) { |
| 468 | std::this_thread::sleep_until(std::chrono::time_point<std::chrono::steady_clock>::max()); | 468 | _U->flagDanglingLanes(); |
| 469 | if (luaG_tostring(L_, kIdxTop) == "freeze") { | ||
| 470 | std::this_thread::sleep_until(std::chrono::time_point<std::chrono::steady_clock>::max()); | ||
| 471 | } else { | ||
| 472 | // take the value returned by the finalizer (or our default message) and throw it as an error | ||
| 473 | // since we are inside Lua's GCTM, it will be propagated through the warning system (Lua 5.4) or swallowed silently | ||
| 474 | // IMPORTANT: lua_error() is used here instead of the wrapper raise_lua_error() to circumvent what looks like a MSVC compiler bug | ||
| 475 | // that manifests as a crash inside ntdll!longjmp() function, in optimized builds only | ||
| 476 | lua_error(L_); | ||
| 477 | } | ||
| 469 | } else { | 478 | } else { |
| 470 | // take the value returned by the finalizer (or our default message) and throw it as an error | 479 | // we didn't use the error message, let's keep a clean stack |
| 471 | // since we are inside Lua's GCTM, it will be propagated through the warning system (Lua 5.4) or swallowed silently | 480 | lua_pop(L_, 1); // L_: U |
| 472 | // IMPORTANT: lua_error() is used here instead of the wrapper raise_lua_error() to circumvent what looks like a MSVC compiler bug | ||
| 473 | // that manifests as a crash inside ntdll!longjmp() function, in optimized builds only | ||
| 474 | lua_error(L_); | ||
| 475 | } | 481 | } |
| 476 | } else { | ||
| 477 | // we didn't use the error message, let's keep a clean stack | ||
| 478 | lua_pop(L_, 1); // L_: U | ||
| 479 | } | 482 | } |
| 480 | STACK_CHECK(L_, 1); | 483 | STACK_CHECK(L_, 1); |
| 481 | 484 | ||
