From 89e7a06deb6d353f6e4d46ebfcd919a06f6e933d Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 13 Sep 2018 18:27:05 +0800 Subject: [PATCH] add more info when service init blocked --- lualib/skynet.lua | 40 +++++++++++++++++++++++++++++++--------- service/launcher.lua | 14 ++++++++++++++ service/service_mgr.lua | 28 ++++++++++++++++++++++------ 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/lualib/skynet.lua b/lualib/skynet.lua index 68aa5d9c..789cb77c 100644 --- a/lualib/skynet.lua +++ b/lualib/skynet.lua @@ -12,6 +12,7 @@ local profile = require "skynet.profile" local cresume = profile.resume local running_thread = nil +local init_thread = nil local function coroutine_resume(co, ...) running_thread = co @@ -219,6 +220,7 @@ function skynet.timeout(ti, func) local co = co_create(func) assert(session_id_coroutine[session] == nil) session_id_coroutine[session] = co + return co -- for debug end local function suspend_sleep(session, token) @@ -770,8 +772,9 @@ end function skynet.start(start_func) c.callback(skynet.dispatch_message) - skynet.timeout(0, function() + init_thread = skynet.timeout(0, function() skynet.init_service(start_func) + init_thread = nil end) end @@ -788,22 +791,41 @@ function skynet.stat(what) end 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] if co then return debug.traceback(co) else return "No session" end - end - local t = 0 - for session,co in pairs(session_id_coroutine) do - if ret then - ret[session] = debug.traceback(co) + elseif tt == "thread" then + for session, co in pairs(session_id_coroutine) do + if co == ret then + return session + end end - t = t + 1 + return end - return t end function skynet.term(service) diff --git a/service/launcher.lua b/service/launcher.lua index 272a459a..d458d13e 100644 --- a/service/launcher.lua +++ b/service/launcher.lua @@ -6,6 +6,7 @@ local string = string local services = {} local command = {} 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) return tonumber("0x" .. string.sub(handle , 2)) @@ -68,6 +69,7 @@ function command.REMOVE(_, handle, kill) -- instance is dead response(not kill) -- return nil to caller of newservice, when kill == false instance[handle] = nil + launch_session[handle] = nil end -- don't return (skynet.ret) because the handle may exit @@ -77,10 +79,12 @@ end local function launch_service(service, ...) local param = table.concat({...}, " ") local inst = skynet.launch(service, param) + local session = skynet.context() local response = skynet.response() if inst then services[inst] = service .. " " .. param instance[inst] = response + launch_session[inst] = session else response(false) return @@ -107,6 +111,7 @@ function command.ERROR(address) local response = instance[address] if response then response(false) + launch_session[address] = nil instance[address] = nil end services[address] = nil @@ -119,11 +124,20 @@ function command.LAUNCHOK(address) if response then response(true, address) instance[address] = nil + launch_session[address] = nil end return NORET 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) skynet.register_protocol { diff --git a/service/service_mgr.lua b/service/service_mgr.lua index e1efeb41..c4d6273c 100644 --- a/service/service_mgr.lua +++ b/service/service_mgr.lua @@ -42,12 +42,17 @@ local function waitfor(name , func, ...) assert(type(s) == "table") - if not s.launch and func then - s.launch = true + local session, source = skynet.context() + + if s.launch == nil and func then + s.launch = { + session = session, + source = source, + co = co, + } return request(name, func, ...) end - local session, source = skynet.context() table.insert(s, { co = co, session = session, @@ -96,9 +101,20 @@ local function list_service() if type(v) == "string" then v = "Error: " .. v elseif type(v) == "table" then - local querying = { "Querying:" } - for _, detail in ipairs(v) do - table.insert(querying, skynet.address(detail.source) .. " " .. tostring(skynet.call(detail.source, "debug", "TASK", detail.session))) + local querying = {} + if v.launch then + 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 v = table.concat(querying, "\n") else