add more info when service init blocked

This commit is contained in:
Cloud Wu
2018-09-13 18:27:05 +08:00
parent 43d02ac456
commit 89e7a06deb
3 changed files with 67 additions and 15 deletions

View File

@@ -12,6 +12,7 @@ local profile = require "skynet.profile"
local cresume = profile.resume local cresume = profile.resume
local running_thread = nil local running_thread = nil
local init_thread = nil
local function coroutine_resume(co, ...) local function coroutine_resume(co, ...)
running_thread = co running_thread = co
@@ -219,6 +220,7 @@ function skynet.timeout(ti, func)
local co = co_create(func) local co = co_create(func)
assert(session_id_coroutine[session] == nil) assert(session_id_coroutine[session] == nil)
session_id_coroutine[session] = co session_id_coroutine[session] = co
return co -- for debug
end end
local function suspend_sleep(session, token) local function suspend_sleep(session, token)
@@ -770,8 +772,9 @@ end
function skynet.start(start_func) function skynet.start(start_func)
c.callback(skynet.dispatch_message) c.callback(skynet.dispatch_message)
skynet.timeout(0, function() init_thread = skynet.timeout(0, function()
skynet.init_service(start_func) skynet.init_service(start_func)
init_thread = nil
end) end)
end end
@@ -788,22 +791,41 @@ function skynet.stat(what)
end end
function skynet.task(ret) function skynet.task(ret)
if type(ret) == "number" then if ret == nil then
local t = 0
for session,co in pairs(session_id_coroutine) do
t = t + 1
end
return t
end
if ret == "init" then
if init_thread then
return debug.traceback(init_thread)
else
return
end
end
local tt = type(ret)
if tt == "table" then
for session,co in pairs(session_id_coroutine) do
ret[session] = debug.traceback(co)
end
return
elseif tt == "number" then
local co = session_id_coroutine[ret] local co = session_id_coroutine[ret]
if co then if co then
return debug.traceback(co) return debug.traceback(co)
else else
return "No session" return "No session"
end end
end elseif tt == "thread" then
local t = 0 for session, co in pairs(session_id_coroutine) do
for session,co in pairs(session_id_coroutine) do if co == ret then
if ret then return session
ret[session] = debug.traceback(co) end
end end
t = t + 1 return
end end
return t
end end
function skynet.term(service) function skynet.term(service)

View File

@@ -6,6 +6,7 @@ local string = string
local services = {} local services = {}
local command = {} local command = {}
local instance = {} -- for confirm (function command.LAUNCH / command.ERROR / command.LAUNCHOK) local instance = {} -- for confirm (function command.LAUNCH / command.ERROR / command.LAUNCHOK)
local launch_session = {} -- for command.QUERY, service_address -> session
local function handle_to_address(handle) local function handle_to_address(handle)
return tonumber("0x" .. string.sub(handle , 2)) return tonumber("0x" .. string.sub(handle , 2))
@@ -68,6 +69,7 @@ function command.REMOVE(_, handle, kill)
-- instance is dead -- instance is dead
response(not kill) -- return nil to caller of newservice, when kill == false response(not kill) -- return nil to caller of newservice, when kill == false
instance[handle] = nil instance[handle] = nil
launch_session[handle] = nil
end end
-- don't return (skynet.ret) because the handle may exit -- don't return (skynet.ret) because the handle may exit
@@ -77,10 +79,12 @@ end
local function launch_service(service, ...) local function launch_service(service, ...)
local param = table.concat({...}, " ") local param = table.concat({...}, " ")
local inst = skynet.launch(service, param) local inst = skynet.launch(service, param)
local session = skynet.context()
local response = skynet.response() local response = skynet.response()
if inst then if inst then
services[inst] = service .. " " .. param services[inst] = service .. " " .. param
instance[inst] = response instance[inst] = response
launch_session[inst] = session
else else
response(false) response(false)
return return
@@ -107,6 +111,7 @@ function command.ERROR(address)
local response = instance[address] local response = instance[address]
if response then if response then
response(false) response(false)
launch_session[address] = nil
instance[address] = nil instance[address] = nil
end end
services[address] = nil services[address] = nil
@@ -119,11 +124,20 @@ function command.LAUNCHOK(address)
if response then if response then
response(true, address) response(true, address)
instance[address] = nil instance[address] = nil
launch_session[address] = nil
end end
return NORET return NORET
end end
function command.QUERY(_, request_session)
for address, session in pairs(launch_session) do
if session == request_session then
return address
end
end
end
-- for historical reasons, launcher support text command (for C service) -- for historical reasons, launcher support text command (for C service)
skynet.register_protocol { skynet.register_protocol {

View File

@@ -42,12 +42,17 @@ local function waitfor(name , func, ...)
assert(type(s) == "table") assert(type(s) == "table")
if not s.launch and func then local session, source = skynet.context()
s.launch = true
if s.launch == nil and func then
s.launch = {
session = session,
source = source,
co = co,
}
return request(name, func, ...) return request(name, func, ...)
end end
local session, source = skynet.context()
table.insert(s, { table.insert(s, {
co = co, co = co,
session = session, session = session,
@@ -96,9 +101,20 @@ local function list_service()
if type(v) == "string" then if type(v) == "string" then
v = "Error: " .. v v = "Error: " .. v
elseif type(v) == "table" then elseif type(v) == "table" then
local querying = { "Querying:" } local querying = {}
for _, detail in ipairs(v) do if v.launch then
table.insert(querying, skynet.address(detail.source) .. " " .. tostring(skynet.call(detail.source, "debug", "TASK", detail.session))) local session = skynet.task(v.launch.co)
local launching_address = skynet.call(".launcher", "lua", "QUERY", session)
table.insert(querying, "Init as " .. skynet.address(launching_address))
table.insert(querying, tostring(skynet.call(launching_address, "debug", "TASK", "init")))
table.insert(querying, "Launching from " .. skynet.address(v.launch.source))
table.insert(querying, tostring(skynet.call(v.launch.source, "debug", "TASK", v.launch.session)))
end
if #v > 0 then
table.insert(querying , "Querying:" )
for _, detail in ipairs(v) do
table.insert(querying, skynet.address(detail.source) .. " " .. tostring(skynet.call(detail.source, "debug", "TASK", detail.session)))
end
end end
v = table.concat(querying, "\n") v = table.concat(querying, "\n")
else else