-
Notifications
You must be signed in to change notification settings - Fork 517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot display "_G.package.loaded" value #446
Comments
Mattes, are you using tolua? The only reference that seems to be relevant that I could find is in tolua sources. The line in mobdebug where it fails is this: If that's the case, it doesn't seem to be ZBS or Mobdebug related as it's strange to have a table that doesn't allow checking for arbitrary keys (and I'm not sure how I'd fix this). |
Yes, MCServer does use tolua for the bindings. I'd expect the debugger to report an error only on such a sub-table, but still be able to display the parent table's contents. This way, I can't view |
Not sure; this looks like tolua bug/deficiency. I don't mind adding specific code to handle important cases, but in this case Did you figure out why you get this error in the first place? Is it incorrect handling of metatables? It looks like you should get the same error in your script (outside of mobdebug/serpent) if you do |
Turns out the I investigated a bit further. I copied the serialization code from mobdebug.lua to my script, so that I could call it, too, and then ran it against The problem is in the interaction with tolua. I have a C++ global array exported through it, and tolua generates metamethods for accessing elements in the array using a numerical index. MobDebug, however, tries to index using a string, Is the |
That's the strange thing: mobdebug tries to access
It creates a new context, so the original can be properly restored on a failure, so it's definitely more expensive than a normal function call; by how much it's difficult to say. I'm not against wrapping it into a |
The problem is that the metatable for that exported symbol is equal to the table itself ( |
Right, but I'm still confused: how is this tolua "trick" supposed to work with all other metatable-related functions in Lua? Sure some of them would need to use |
To be honest, I have no idea how this works, this is too low-level for me. I suppose this number-restricted metatable is used only for the arrays, that would make some sense. If you want me to test some code changes in Serpent, you'd need to be a bit more specific about what to modify in order to test. |
You don't need to change Serpent; I'd be interested to see if the following fragment triggers the error: -- assuming your Array variable is called array
print(rawget(getmetatable(array), "__tostring")) -- should work
print(pcall(function() return getmetatable(array).__tostring end)) -- should work
print(getmetatable(array).__tostring) -- should fail |
Exactly as you expected. The first line prints |
Good; thank you for the update. I can use diff --git a/lualibs/mobdebug/mobdebug.lua b/lualibs/mobdebug/mobdebug.lua
index 89d6be4..32a3b1d 100644
--- a/lualibs/mobdebug/mobdebug.lua
+++ b/lualibs/mobdebug/mobdebug.lua
@@ -175,9 +175,9 @@ local function s(t, opts)
if seen[t] then -- already seen this element
sref[#sref+1] = spath..space..'='..space..seen[t]
return tag..'nil'..comment('ref', level) end
- if type(mt) == 'table' and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
+ if type(mt) == 'table' and (rawget(mt, "__serialize") or rawget(mt, "__tostring")) then -- knows how to serialize itself
seen[t] = insref or spath
- if mt.__serialize then t = mt.__serialize(t) else t = tostring(t) end
+ if rawget(mt, "__serialize") then t = mt.__serialize(t) else t = tostring(t) end
ttype = type(t) end -- new value falls through to be serialized
if ttype == "table" then
if level >= maxl then return tag..'{}'..comment('max', level) end The main flipside is that it only checks the metatable and it may have its own metatables, which are not checked. The alternative using |
Yes, this change has fixed the issue for me. |
@madmaxoft, can you also check the following patch: diff --git a/lualibs/mobdebug/mobdebug.lua b/lualibs/mobdebug/mobdebug.lua
index 89d6be4..a1c7dd5 100644
--- a/lualibs/mobdebug/mobdebug.lua
+++ b/lualibs/mobdebug/mobdebug.lua
@@ -175,7 +175,8 @@ local function s(t, opts)
if seen[t] then -- already seen this element
sref[#sref+1] = spath..space..'='..space..seen[t]
return tag..'nil'..comment('ref', level) end
- if type(mt) == 'table' and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
+ if type(mt) == 'table' and pcall(function() return mt.__tostring end)
+ and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
seen[t] = insref or spath
if mt.__serialize then t = mt.__serialize(t) else t = tostring(t) end
ttype = type(t) end -- new value falls through to be serialized |
Yes, this works as well. |
@madmaxoft, could you also try this more complete fix? Thanks! diff --git a/lualibs/mobdebug/mobdebug.lua b/lualibs/mobdebug/mobdebug.lua
index 99e8e4a..d44c8f9 100644
--- a/lualibs/mobdebug/mobdebug.lua
+++ b/lualibs/mobdebug/mobdebug.lua
@@ -127,7 +127,7 @@ end
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
local serpent = (function() ---- include Serpent module for serialization
-local n, v = "serpent", 0.28 -- (C) 2012-15 Paul Kulchenko; MIT License
+local n, v = "serpent", 0.281 -- (C) 2012-15 Paul Kulchenko; MIT License
local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
local badtype = {thread = true, userdata = true, cdata = true}
@@ -151,7 +151,7 @@ local function s(t, opts)
local function safestr(s) return type(s) == "number" and tostring(huge and snum[tostring(s)] or s)
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end
- local function comment(s,l) return comm and (l or 0) < comm and ' --[['..tostring(s)..']]' or '' end
+ local function comment(s,l) return comm and (l or 0) < comm and ' --[['..select(2, pcall(tostring, s))..']]' or '' end
local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal
and safestr(select(2, pcall(tostring, s))) or error("Can't serialize "..tostring(s)) end
local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
@@ -175,7 +175,9 @@ local function s(t, opts)
if seen[t] then -- already seen this element
sref[#sref+1] = spath..space..'='..space..seen[t]
return tag..'nil'..comment('ref', level) end
- if type(mt) == 'table' and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
+ -- protect from those cases where __tostring may fail
+ if type(mt) == 'table' and pcall(function() return mt.__tostring and mt.__tostring(t) end)
+ and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
seen[t] = insref or spath
if mt.__serialize then t = mt.__serialize(t) else t = tostring(t) end
ttype = type(t) end -- new value falls through to be serialized |
Yes, that fixes the issue for me, too. |
When I run my script in the MCServer interpreter ( https://github.com/mc-server/MCServer ) and it hits a breakpoint, there's no way to view the value of
package
orpackage.loaded
. Instead of the expected table, the watch window shows this text:The same happens when trying to print the value in the Remote console window using
=package.loaded
command.When running a script in the regular Lua interpreter, the value is displayed correctly, so this issue does depend on the interpreter.
Running ZBS commit e24ee26 on Windows 7 64-bit, although I remember seeing this issue earlier, perhaps a month or two back, so it's nothing new, I just didn't need it that much so I didn't report it.
The text was updated successfully, but these errors were encountered: