Fix skynet.require recursion issue, See #1331

This commit is contained in:
Cloud Wu
2021-01-25 10:34:01 +08:00
parent 30279f2f8d
commit 4532d4f146

View File

@@ -17,21 +17,76 @@ local context = {
do
local require = _G.require
function M.require(...)
local loaded = package.loaded
local loading = {}
function M.require(name)
local m = loaded[name]
if m ~= nil then
return m
end
local co, main = coroutine.running()
if main then
return require(...)
else
local old_init_list = context[co]
local init_list = {}
context[co] = init_list
local ret = require(...)
for _, f in ipairs(init_list) do
f()
end
context[co] = old_init_list
return ret
return require(name)
end
local filename = package.searchpath(name, package.path)
if not filename then
return require(name)
end
local modfunc = loadfile(filename)
if not modfunc then
return require(name)
end
local loading_queue = loading[name]
if loading_queue then
-- Module is in the init process (require the same mod at the same time in different coroutines) , waiting.
local skynet = require "skynet"
loading_queue[#loading_queue+1] = co
print ("Waiting " .. name)
skynet.wait(co)
local m = loaded[name]
print ("Waiting OK : " .. tostring(m))
if m == nil then
error(string.format("require %s failed", name))
end
return m
end
loading_queue = {}
loading[name] = loading_queue
local old_init_list = context[co]
local init_list = {}
context[co] = init_list
-- We should call modfunc in lua, because modfunc may yield by calling M.require recursive.
local m = modfunc(name, filename)
for _, f in ipairs(init_list) do
f()
end
context[co] = old_init_list
if m == nil then
m = true
end
package.loaded[name] = m
local waiting = #loading_queue
if waiting > 0 then
local skynet = require "skynet"
for i = 1, waiting do
skynet.wakeup(loading_queue[i])
end
end
loading[name] = nil
return m
end
end