Closed sewbacca closed 3 years ago
Apologies for not responding to this sooner.
Coroutines work similar to pcall as they catch their own errors, so the debugger doesn't break on them by design. However it should not break inside the debugger code like this, but one level up. This is a bug.
Thinking about it, it would be good to have an option to break on errors in coroutines, since that's probably what most people would expect to happen. I'll look into adding that functionality.
I've fixed the issue with breaking into the debugger code itself and added the ability to break directly into the coroutine when error()
or assert()
are used. Implicit errors will still break outside of the coroutine, though. Because coroutines shut down as soon as the error occurs, there doesn't seem to be a way to intercept before the call stack is gone. I'm keeping this open for now, though, to remind myself to explore further.
Great to see that this project is still maintained 👍
This idea is neither tested, nor really thought through, but couldn't you override coroutine.create
and xpcall()
the given function, so the routine cannot be closed down immediatly?
I've been spread too thin this year, but I have no intention of abandoning this!
Unfortunately, you can't yield through an xpcall, so the coroutines wouldn't work if we tried to inject them like that.
Do you need to? Since you are using io
afaik to communicate with the debugger, I thought you could do something like this:
local createco = coroutine.create
function coroutine.create(func)
return createco(function(...)
local ok = false
local results = {}
xpcall(function() results = { func(...) }; ok = true end, function() --[[ Error checking code and io calls here ]] end)
return table.unpack(results)
end
end
Maybe I have understood something wrong, but to me it seems like this would be the way to go.
In that example, when func
calls coroutine.yield
, the error error: attempt to yield across metamethod/C-call boundary
will occur.
I just checked, though, and this seems to only be a limitation in lua5.1. Later versions seem to allow it, so it might be something we could enable on a per-version basis.
implemented in 1dfd86f
In that example, when
func
callscoroutine.yield
, the errorerror: attempt to yield across metamethod/C-call boundary
will occur.I just checked, though, and this seems to only be a limitation in lua5.1. Later versions seem to allow it, so it might be something we could enable on a per-version basis.
For the time being, this is a work arround (probably only >lua5.1
):
local create = coroutine.create
local wrap = coroutine.wrap
function coroutine.create(f)
return create(function(...)
return unpack(debugger.call(f))
end)
end
function coroutine.wrap(f)
return wrap(function(...)
return unpack(debugger.call(f))
end)
end
This is now supported in version 0.2.3 by enabling breakInCoroutines
in launch.json. When enabled, the debugger will break inside coroutines when an error occurs.
The one caveat to this is that in Lua5.1, implicit errors (those not triggered via calls to error
or assert
) will break where the coroutine resumed instead of at the location they occurred. The real location will be in the error message displayed. This is due to the fact that yield through an xpcall is not possible in 5.1, so catching the error before the stack unwinds is impossible (as far as I know).