diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-29 11:56:33 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-29 11:56:33 +0200 |
| commit | d9400c00c05590e0d0e40e6775dc338d28b92f14 (patch) | |
| tree | d7cab3e197d9131555aa8e77f21e72b24a6e2040 /src | |
| parent | 05921ccb8205a4dcf1897dd8be9aa30a09e9a379 (diff) | |
| download | lanes-d9400c00c05590e0d0e40e6775dc338d28b92f14.tar.gz lanes-d9400c00c05590e0d0e40e6775dc338d28b92f14.tar.bz2 lanes-d9400c00c05590e0d0e40e6775dc338d28b92f14.zip | |
Modernize serialize_require
Diffstat (limited to 'src')
| -rw-r--r-- | src/lanes.cpp | 2 | ||||
| -rw-r--r-- | src/state.cpp | 68 | ||||
| -rw-r--r-- | src/state.h | 2 | ||||
| -rw-r--r-- | src/tools.cpp | 57 | ||||
| -rw-r--r-- | src/tools.h | 4 | ||||
| -rw-r--r-- | src/universe.cpp | 2 |
6 files changed, 64 insertions, 71 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index bd5f69e..a82e4ba 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -684,7 +684,7 @@ LUAG_FUNC(configure) | |||
| 684 | STACK_CHECK(L_, 1); | 684 | STACK_CHECK(L_, 1); |
| 685 | 685 | ||
| 686 | // Serialize calls to 'require' from now on, also in the primary state | 686 | // Serialize calls to 'require' from now on, also in the primary state |
| 687 | serialize_require(L_); | 687 | tools::SerializeRequire(L_); |
| 688 | 688 | ||
| 689 | // Retrieve main module interface table | 689 | // Retrieve main module interface table |
| 690 | lua_pushvalue(L_, lua_upvalueindex(2)); // L_: settings M | 690 | lua_pushvalue(L_, lua_upvalueindex(2)); // L_: settings M |
diff --git a/src/state.cpp b/src/state.cpp index d9f5499..8520346 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
| @@ -43,72 +43,6 @@ THE SOFTWARE. | |||
| 43 | 43 | ||
| 44 | // ################################################################################################# | 44 | // ################################################################################################# |
| 45 | 45 | ||
| 46 | /*---=== Serialize require ===--- | ||
| 47 | */ | ||
| 48 | |||
| 49 | //--- | ||
| 50 | // [val,...]= new_require( ... ) | ||
| 51 | // | ||
| 52 | // Call 'old_require' but only one lane at a time. | ||
| 53 | // | ||
| 54 | // Upvalues: [1]: original 'require' function | ||
| 55 | // | ||
| 56 | [[nodiscard]] static int luaG_new_require(lua_State* L_) | ||
| 57 | { | ||
| 58 | int const _args{ lua_gettop(L_) }; // L_: args | ||
| 59 | Universe* const _U{ universe_get(L_) }; | ||
| 60 | //[[maybe_unused]] std::string_view const _modname{ luaL_checkstringview(L_, 1) }; | ||
| 61 | |||
| 62 | STACK_GROW(L_, 1); | ||
| 63 | |||
| 64 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: args require | ||
| 65 | lua_insert(L_, 1); // L_: require args | ||
| 66 | |||
| 67 | // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would | ||
| 68 | // leave us locked, blocking any future 'require' calls from other lanes. | ||
| 69 | |||
| 70 | _U->requireMutex.lock(); | ||
| 71 | // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET | ||
| 72 | LuaError const _rc{ lua_pcall(L_, _args, LUA_MULTRET, 0 /*errfunc*/) }; // L_: err|result(s) | ||
| 73 | _U->requireMutex.unlock(); | ||
| 74 | |||
| 75 | // the required module (or an error message) is left on the stack as returned value by original require function | ||
| 76 | |||
| 77 | if (_rc != LuaError::OK) { // LUA_ERRRUN / LUA_ERRMEM ? | ||
| 78 | raise_lua_error(L_); | ||
| 79 | } | ||
| 80 | // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4 | ||
| 81 | return lua_gettop(L_); // L_: result(s) | ||
| 82 | } | ||
| 83 | |||
| 84 | // ################################################################################################# | ||
| 85 | |||
| 86 | /* | ||
| 87 | * Serialize calls to 'require', if it exists | ||
| 88 | */ | ||
| 89 | void serialize_require(lua_State* L_) | ||
| 90 | { | ||
| 91 | STACK_GROW(L_, 1); | ||
| 92 | STACK_CHECK_START_REL(L_, 0); | ||
| 93 | DEBUGSPEW_CODE(DebugSpew(universe_get(L_)) << "serializing require()" << std::endl); | ||
| 94 | |||
| 95 | // Check 'require' is there and not already wrapped; if not, do nothing | ||
| 96 | // | ||
| 97 | lua_getglobal(L_, "require"); | ||
| 98 | if (lua_isfunction(L_, -1) && lua_tocfunction(L_, -1) != luaG_new_require) { | ||
| 99 | // [-1]: original 'require' function | ||
| 100 | lua_pushcclosure(L_, luaG_new_require, 1 /*upvalues*/); | ||
| 101 | lua_setglobal(L_, "require"); | ||
| 102 | } else { | ||
| 103 | // [-1]: nil | ||
| 104 | lua_pop(L_, 1); | ||
| 105 | } | ||
| 106 | |||
| 107 | STACK_CHECK(L_, 0); | ||
| 108 | } | ||
| 109 | |||
| 110 | // ################################################################################################# | ||
| 111 | |||
| 112 | /*---=== luaG_newstate ===---*/ | 46 | /*---=== luaG_newstate ===---*/ |
| 113 | 47 | ||
| 114 | [[nodiscard]] static int require_lanes_core(lua_State* L_) | 48 | [[nodiscard]] static int require_lanes_core(lua_State* L_) |
| @@ -397,7 +331,7 @@ lua_State* luaG_newstate(Universe* U_, SourceState from_, std::optional<std::str | |||
| 397 | } | 331 | } |
| 398 | lua_gc(_L, LUA_GCRESTART, 0); | 332 | lua_gc(_L, LUA_GCRESTART, 0); |
| 399 | 333 | ||
| 400 | serialize_require(_L); | 334 | tools::SerializeRequire(_L); |
| 401 | 335 | ||
| 402 | // call this after the base libraries are loaded and GC is restarted | 336 | // call this after the base libraries are loaded and GC is restarted |
| 403 | // will raise an error in from_ in case of problem | 337 | // will raise an error in from_ in case of problem |
diff --git a/src/state.h b/src/state.h index a97fdab..ff70196 100644 --- a/src/state.h +++ b/src/state.h | |||
| @@ -7,8 +7,6 @@ | |||
| 7 | enum class LookupMode; | 7 | enum class LookupMode; |
| 8 | class Universe; | 8 | class Universe; |
| 9 | 9 | ||
| 10 | void serialize_require(lua_State* L_); | ||
| 11 | |||
| 12 | // ################################################################################################# | 10 | // ################################################################################################# |
| 13 | 11 | ||
| 14 | [[nodiscard]] lua_State* create_state(Universe* U_, lua_State* from_); | 12 | [[nodiscard]] lua_State* create_state(Universe* U_, lua_State* from_); |
diff --git a/src/tools.cpp b/src/tools.cpp index 0b10464..d270aac 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
| @@ -526,3 +526,60 @@ int luaG_nameof(lua_State* L_) | |||
| 526 | lua_replace(L_, -3); // L_: "type" "result" | 526 | lua_replace(L_, -3); // L_: "type" "result" |
| 527 | return 2; | 527 | return 2; |
| 528 | } | 528 | } |
| 529 | |||
| 530 | // ################################################################################################# | ||
| 531 | |||
| 532 | namespace tools { | ||
| 533 | |||
| 534 | // Serialize calls to 'require', if it exists | ||
| 535 | void SerializeRequire(lua_State* L_) | ||
| 536 | { | ||
| 537 | static constexpr lua_CFunction _lockedRequire{ | ||
| 538 | +[](lua_State* L_) | ||
| 539 | { | ||
| 540 | int const _args{ lua_gettop(L_) }; // L_: args... | ||
| 541 | //[[maybe_unused]] std::string_view const _modname{ luaL_checkstringview(L_, 1) }; | ||
| 542 | |||
| 543 | STACK_GROW(L_, 1); | ||
| 544 | |||
| 545 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: args... require | ||
| 546 | lua_insert(L_, 1); // L_: require args... | ||
| 547 | |||
| 548 | // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would | ||
| 549 | // leave us locked, blocking any future 'require' calls from other lanes. | ||
| 550 | LuaError const _rc{ std::invoke( | ||
| 551 | [L = L_, args = _args]() | ||
| 552 | { | ||
| 553 | std::lock_guard _guard{ universe_get(L)->requireMutex }; | ||
| 554 | // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET | ||
| 555 | return lua_pcall(L, args, LUA_MULTRET, 0 /*errfunc*/); // L_: err|result(s) | ||
| 556 | }) | ||
| 557 | }; | ||
| 558 | |||
| 559 | // the required module (or an error message) is left on the stack as returned value by original require function | ||
| 560 | |||
| 561 | if (_rc != LuaError::OK) { // LUA_ERRRUN / LUA_ERRMEM ? | ||
| 562 | raise_lua_error(L_); | ||
| 563 | } | ||
| 564 | // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4 | ||
| 565 | return lua_gettop(L_); // L_: result(s) | ||
| 566 | } | ||
| 567 | }; | ||
| 568 | |||
| 569 | STACK_GROW(L_, 1); | ||
| 570 | STACK_CHECK_START_REL(L_, 0); | ||
| 571 | DEBUGSPEW_CODE(DebugSpew(universe_get(L_)) << "serializing require()" << std::endl); | ||
| 572 | |||
| 573 | // Check 'require' is there and not already wrapped; if not, do nothing | ||
| 574 | lua_getglobal(L_, "require"); // L_: _G.require()|nil | ||
| 575 | if (lua_isfunction(L_, -1) && lua_tocfunction(L_, -1) != _lockedRequire) { | ||
| 576 | lua_pushcclosure(L_, _lockedRequire, 1 /*upvalues*/); // L_: _lockedRequire() | ||
| 577 | lua_setglobal(L_, "require"); // L_: | ||
| 578 | } else { | ||
| 579 | lua_pop(L_, 1); // L_: | ||
| 580 | } | ||
| 581 | |||
| 582 | STACK_CHECK(L_, 0); | ||
| 583 | } | ||
| 584 | } // namespace tools | ||
| 585 | |||
diff --git a/src/tools.h b/src/tools.h index 4857eeb..3659b42 100644 --- a/src/tools.h +++ b/src/tools.h | |||
| @@ -26,6 +26,10 @@ enum class FuncSubType | |||
| 26 | 26 | ||
| 27 | void populate_func_lookup_table(lua_State* const L_, int const i_, std::string_view const& name_); | 27 | void populate_func_lookup_table(lua_State* const L_, int const i_, std::string_view const& name_); |
| 28 | 28 | ||
| 29 | namespace tools { | ||
| 30 | void SerializeRequire(lua_State* L_); | ||
| 31 | } // namespace tools | ||
| 32 | |||
| 29 | // ################################################################################################# | 33 | // ################################################################################################# |
| 30 | 34 | ||
| 31 | // xxh64 of string "kConfigRegKey" generated at https://www.pelock.com/products/hash-calculator | 35 | // xxh64 of string "kConfigRegKey" generated at https://www.pelock.com/products/hash-calculator |
diff --git a/src/universe.cpp b/src/universe.cpp index 620be79..172cc4c 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
| @@ -287,7 +287,7 @@ void Universe::initializeKeepers(lua_State* L_) | |||
| 287 | luaL_requiref(_K, LUA_LOADLIBNAME, luaopen_package, 1); // L_: settings K: package | 287 | luaL_requiref(_K, LUA_LOADLIBNAME, luaopen_package, 1); // L_: settings K: package |
| 288 | lua_pop(_K, 1); // L_: settings K: | 288 | lua_pop(_K, 1); // L_: settings K: |
| 289 | STACK_CHECK(_K, 0); | 289 | STACK_CHECK(_K, 0); |
| 290 | serialize_require(_K); | 290 | tools::SerializeRequire(_K); |
| 291 | STACK_CHECK(_K, 0); | 291 | STACK_CHECK(_K, 0); |
| 292 | 292 | ||
| 293 | // copy package.path and package.cpath from the source state | 293 | // copy package.path and package.cpath from the source state |
