actboy168 / lua-debug

Lua Debug Adapter for Visual Studio Code
MIT License
439 stars 95 forks source link

Assertion Errors pauses execution even when disabled #264

Open thewhitegoatcb opened 1 year ago

thewhitegoatcb commented 1 year ago

Asserts caused when they are disabled causes to pause execution without poping any errors or showing a paused state image State shows as running: image Enabling them in that state immediately shows the assert error that caused the pause and enables to continue execution manually

actboy168 commented 1 year ago

@fesily

fesily commented 1 year ago

Cannot be reproduced, provide minimum reproduction example.

thewhitegoatcb commented 1 year ago

Sorry for the delay, I cannot reproduce on a minimal setup. It's intermittent so a bit hard to track.

thewhitegoatcb commented 1 year ago

Checked it today, apparently local function traceback(flags, error) was profiled at 500-700ms for each exception. A way to reproduce would be to run a lot of asserts in a a protected loop with at least one of the exception filters enabled that isn't related to the assert. My temp fix is adding


function m.hasExceptionFilters(flags)
    for _, flag in ipairs(flags) do
        if exceptionFilters[flag] ~= nil then
            return true
        end
    end
    return false
end

....

local function runException(flags, errobj)
    if not breakpoint.hasExceptionFilters(flags) then 
        return 
    end

....
fesily commented 1 year ago

Do you mean that the traceback is too slow to cause this problem. I still can't reproduce what you said

while true do
  pcall(function ()
    while true do
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(true)
      assert(false)
    end
  end)
end
thewhitegoatcb commented 1 year ago

Narrowed it down to local function findfield(t, f, level) being expensive to run on big environments with a lot of globals, we should find a way to cache the name or location of the function. Imo it isn't a big issue but currently this will happen if any exception catching is enabled even if it's not the one that is related to the assert. So my quick fix I proposed earlier might be good enough for now. Here's a test case, this runs at about 100ms per loop on my machine

local function create_big_env(num_tables, table_size)
    for i=1, num_tables do
        local T = {}
        for j=1, table_size do
            T["k"..j] = 123
        end
        rawset(_G, "T"..i, T)
    end
end

local function test()
    while true do
        local start = os.clock()
        pcall(function ()
            assert(false)
        end)
        print(os.clock() - start)
    end
end

create_big_env(100, 1000)
test()
fesily commented 1 year ago

So the initial problem was caused by the slow running of the filter exception function, I can assume so?

thewhitegoatcb commented 1 year ago

Yes, it's not a luajit specific issue it seems

fesily commented 1 year ago

You can submit a pull