Skip to content

PCall breaks metamethods #41

@EntranceJew

Description

@EntranceJew

While it's intuitive that you be prepared to () a function exclusively, if a table has a __call metamethod it will break. When I attempted to route PCallDebug through PCall for testing purposes, this was the source of an infinite black loading screen error.

The make or break difference between the two is whether or not it actually returns any arguments, because the blank return lines were killing but piping results back out cleared it up.

I was incidentally trying to replace the pcall with xpcall (but it seems like IHHook doesn't have the address of xpcall anywhere, so i'm not sure if that function is usable the way I intended?)

Here's the snippet of what I monkeypatched the two PCall functions to be from outside of InfCore:

InfCore.PCall=function(func,...)
    --[[
    -- these cause a fair bit of problems being left this way
    if func==nil then
        InfCore.Log("PCall func == nil")
      return
    elseif type(func)~=functionType then
        InfCore.Log("PCall func~=function")
      return
    end
    ]]
    local result={pcall(func,...)}
    local sucess=table.remove(result,1)
    if not sucess then
        local trace = debug.traceback()

        local source = {}
        local cause
        for _,v in ipairs(result) do
            for word in v:gmatch("([^:]+:%d+: )") do
                cause = v:gsub(word, "")
                source[#source+1] = word .. "[source]"
            end
        end
        local traces = InfUtil.Split(trace, "\n\t")
        table.remove(traces, 1) -- ignore "stack traceback:" line
        for i = #traces, 1, -1 do
            local v = traces[i]
            if v == "(tail call): ?" then
                traces[i-1] = traces[i-1] .. " " .. v
            else
                source[#source+1] = v
            end
        end

        local neotrace = cause .. "\n\t" .. table.concat(source, "\n\t")
        InfCore.Log("ERROR: ".. neotrace,false,"error")
        return unpack(result)
    else
      return unpack(result)
    end
end
--tex as above but intended to pass through unless debugmode on
InfCore.PCallDebug=function(func,...)
    if not InfCore.debugMode then
      return func(...)
    else
      --ej: i do not see a reason to duplicate this code \o/
      return InfCore.PCall(func, ...)
    end
end

I didn't want to jump directly into a PR with this because it could dramatically affect execution, but after playing around with this bit of code in particular, I haven't seen much go wrong other than what I mentioned here in the process of throwing a detailed trace into the equation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions