summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Desgats2013-02-01 13:00:07 (EST)
committerSimon Bernard2013-02-26 11:34:18 (EST)
commitdf6dc1287375fca5905a5b999e0fe62d008f9d41 (patch)
tree0d653145750f3c83f664adce1fd872d74739e0d2
parent84ceb600f76bf826788e4117d8e9158b1d3b06dd (diff)
downloadorg.eclipse.koneki.ldt-df6dc1287375fca5905a5b999e0fe62d008f9d41.zip
org.eclipse.koneki.ldt-df6dc1287375fca5905a5b999e0fe62d008f9d41.tar.gz
org.eclipse.koneki.ldt-df6dc1287375fca5905a5b999e0fe62d008f9d41.tar.bz2
Bug 398531 : Fixed error with LuaJIT 2.0 without 5.2 compatibility
Current debugging logic was based on the assumption that coroutine.running() can return main thread, which is the case only when LuaJIT is compiled with LUAJIT_ENABLE_LUA52COMPAT. Now the debugger can be started on the top of user code, just like with regular 5.1 (with some modifications due to different tail call handling)
-rw-r--r--libraries/luadbgpclient/debugger/init.lua36
-rw-r--r--libraries/luadbgpclient/debugger/platform.lua2
-rw-r--r--libraries/luadbgpclient/debugger/util.lua72
3 files changed, 66 insertions, 44 deletions
diff --git a/libraries/luadbgpclient/debugger/init.lua b/libraries/luadbgpclient/debugger/init.lua
index a228045..2f4530b 100644
--- a/libraries/luadbgpclient/debugger/init.lua
+++ b/libraries/luadbgpclient/debugger/init.lua
@@ -412,7 +412,7 @@ end
if jit then
debugger_hook = function(event, line)
- local thread = corunning()
+ local thread = corunning() or "main"
if event == "call" then
if debug.getinfo(2, "S").what == "C" then return end
stack_levels[thread] = stack_levels[thread] + 1
@@ -425,7 +425,12 @@ if jit then
stack_levels[thread] = depth - 2
elseif event == "line" then
active_session.coro = util.CurrentThread(corunning())
- assert(coresume(line_hook_coro, line))
+ if active_session.coro[1] == "main" then
+ line_hook(line)
+ else
+ -- run the debugger loop in another thread on the other cases (simplifies stack handling)
+ assert(coresume(line_hook_coro, line))
+ end
active_session.coro = nil
end
end
@@ -436,22 +441,22 @@ local function init(host, port, idekey, transport, executionplatform, workingdir
local host = host or os.getenv "DBGP_IDEHOST" or "127.0.0.1"
local port = port or os.getenv "DBGP_IDEPORT" or "10000"
local idekey = idekey or os.getenv("DBGP_IDEKEY") or "luaidekey"
-
+
-- init plaform module
local executionplatform = executionplatform or os.getenv("DBGP_PLATFORM") or nil
local workingdirectory = workingdirectory or os.getenv("DBGP_WORKINGDIR") or nil
platform.init(executionplatform,workingdirectory)
-
+
-- get transport layer
local transportpath = transport or os.getenv("DBGP_TRANSPORT") or "debugger.transport.luasocket"
local transport = require(transportpath)
-
+
-- install base64 functions into util
util.b64, util.rawb64, util.unb64 = transport.b64, transport.rawb64, transport.unb64
-
+
local skt = assert(transport.create())
skt:settimeout(nil)
-
+
-- try to connect several times: if IDE launches both process and server at same time, first connect attempts may fail
local ok, err
for i=1, 5 do
@@ -460,11 +465,11 @@ local function init(host, port, idekey, transport, executionplatform, workingdir
transport.sleep(0.5)
end
if err then error(string.format("Cannot connect to %s:%d : %s", host, port, err)) end
-
+
-- get the debugger and transport layer URI
debugger_uri = platform.get_uri(debug.getinfo(1).source)
transportmodule_uri = platform.get_uri(debug.getinfo(transport.create).source)
-
+
-- get the root script path (the highest possible stack index)
local source
for i=2, math.huge do
@@ -473,14 +478,14 @@ local function init(host, port, idekey, transport, executionplatform, workingdir
source = platform.get_uri(info.source) or source
end
if not source then source = "unknown:/" end -- when loaded before actual script (with a command line switch)
-
+
-- generate some kind of thread identifier
local thread = corunning() or "main"
stack_levels[thread] = 1 -- the return event will set the counter to 0
local sessionid = tostring(os.time()) .. "_" .. tostring(thread)
-
+
dbgp.send_xml(skt, { tag = "init", attr = {
- appid = "Lua DBGp",
+ appid = "Lua DBGp",
idekey = idekey,
session = sessionid,
thread = tostring(thread),
@@ -489,14 +494,15 @@ local function init(host, port, idekey, transport, executionplatform, workingdir
protocol_version = "1.0",
fileuri = source
} })
-
+
+ --FIXME util.CurrentThread(corunning) => util.CurrentThread(corunning()) WHAT DOES IT FIXES ??
local sess = { skt = skt, state = "starting", id = sessionid, coro = util.CurrentThread(corunning) }
active_session = sess
debugger_loop(sess)
-
+
-- set debug hooks
debug.sethook(debugger_hook, "rlc")
-
+
-- install coroutine collecting functions.
-- TODO: maintain a list of *all* coroutines can be overkill (for example, the ones created by copcall), make a extension point to
-- customize debugged coroutines
diff --git a/libraries/luadbgpclient/debugger/platform.lua b/libraries/luadbgpclient/debugger/platform.lua
index c0035f4..7a1cb4e 100644
--- a/libraries/luadbgpclient/debugger/platform.lua
+++ b/libraries/luadbgpclient/debugger/platform.lua
@@ -148,7 +148,7 @@ function M.init(executionplatform,workingdirectory)
return false
end
- status, iswin = pcall(iswindows)
+ local status, iswin = pcall(iswindows)
if status and iswin then
platform = "win"
else
diff --git a/libraries/luadbgpclient/debugger/util.lua b/libraries/luadbgpclient/debugger/util.lua
index abc52e5..f7cdaa3 100644
--- a/libraries/luadbgpclient/debugger/util.lua
+++ b/libraries/luadbgpclient/debugger/util.lua
@@ -87,41 +87,57 @@ local CurrentThreadMT = {
CurrentThreadMT.__index = CurrentThreadMT
function M.CurrentThread(coro) return setmetatable({ coro }, CurrentThreadMT) end
--- Fallback method to inspect running thread (only for main thread in 5.1 or for conditional breakpoints)
---- Gets a script stack level with additional debugger logic added
--- @param l (number) stack level to get for debugged script (0 based)
--- @return real Lua stack level suitable to be passed through deubg functions
-local function get_script_level(l)
- local hook = debug.gethook()
- for i=2, math.huge do
- if assert(debug.getinfo(i, "f")).func == hook then
- return i + l -- the script to level is just below, but because of the extra call to this function, the level is ok for callee
- end
- end
-end
-M.MainThread = {
- [1] = "main", -- as the raw thread object is used as table keys, provide a replacement.
- getinfo = function(self, level, what) return getinfo(get_script_level(level), what:gsub("t", "", 1)) end,
- getlocal = function(self, level, idx) return getlocal(get_script_level(level), idx) end,
- setlocal = function(self, level, idx, val) return setlocal(get_script_level(level), idx, val) end,
-}
-- Some version dependant functions
if _VERSION == "Lua 5.1" then
- local loadstring, getfenv, setfenv, debug_getinfo = loadstring, getfenv, setfenv, debug.getinfo
-
+ local loadstring, getfenv, setfenv, debug_getinfo, MainThread =
+ loadstring, getfenv, setfenv, debug.getinfo, nil
+
-- in 5.1 "t" flag does not exist and trigger an error so remove it from what
CurrentThreadMT.getinfo = function(self, level, what) return getinfo(self[1], level + 2, what:gsub("t", "", 1)) end
ForeignThreadMT.getinfo = function(self, level, what) return getinfo(self[1], level, what:gsub("t", "", 1)) end
-
- -- If the VM is vanilla Lua 5.1, there is no way to get a reference to the main coroutine, so fall back to direct mode:
- -- the debugger loop is started on the top of main thread and the actual level is recomputed each time
- if not jit then
- -- allow CurrentThread to take a nil parameter
- local oldCurrentThread = M.CurrentThread
- M.CurrentThread = function(coro) return coro and oldCurrentThread(coro) or M.MainThread end
+
+ -- when we're forced to start debug loop on top of program stack (when on main coroutine)
+ -- this requires some hackery to get right stack level
+
+ -- Fallback method to inspect running thread (only for main thread in 5.1 or for conditional breakpoints)
+ --- Gets a script stack level with additional debugger logic added
+ -- @param l (number) stack level to get for debugged script (0 based)
+ -- @return real Lua stack level suitable to be passed through deubg functions
+ local function get_script_level(l)
+ local hook = debug.gethook()
+ for i=2, math.huge do
+ if assert(debug.getinfo(i, "f")).func == hook then
+ return i + l -- the script to level is just below, but because of the extra call to this function, the level is ok for callee
+ end
+ end
end
-
+
+ if jit then
+ MainThread = {
+ [1] = "main", -- as the raw thread object is used as table keys, provide a replacement.
+ -- LuaJIT completely eliminates tail calls from stack, so get_script_level retunrs wrong result in this case
+ getinfo = function(self, level, what) return getinfo(get_script_level(level) - 1, what:gsub("t", "", 1)) end,
+ getlocal = function(self, level, idx) return getlocal(get_script_level(level) - 1, idx) end,
+ setlocal = function(self, level, idx, val) return setlocal(get_script_level(level) - 1, idx, val) end,
+ }
+ else
+ MainThread = {
+ [1] = "main",
+ getinfo = function(self, level, what) return getinfo(get_script_level(level) , what:gsub("t", "", 1)) end,
+ getlocal = function(self, level, idx) return getlocal(get_script_level(level), idx) end,
+ setlocal = function(self, level, idx, val) return setlocal(get_script_level(level), idx, val) end,
+ }
+ end
+
+
+
+ -- If the VM is vanilla Lua 5.1 or LuaJIT 2 without 5.2 compatibility, there is no way to get a reference to
+ -- the main coroutine, so fall back to direct mode: the debugger loop is started on the top of main thread
+ -- and the actual level is recomputed each time
+ local oldCurrentThread = M.CurrentThread
+ M.CurrentThread = function(coro) return coro and oldCurrentThread(coro) or MainThread end
+
-- load a piece of code alog with its environment
function M.loadin(code, env)
local f = loadstring(code)