coroutine.wrap(function()
local co = coroutine.running()
local function f()
task.wait(2)
coroutine.resume(co)
end
task.spawn(f)
task.wait(5)
print("wait interrupted")
end)
Expected Behavior
I’d expect the following code to print "wait interrupted" after 2 seconds.
Actual Behavior
It does this, but errors at some point with the message “attempt to call a nil value”, that has no traceback (meaning it’s an internal error). Most importantly, the error happens after 5 seconds, so after the second wait has stopped yielding and is planning to resume the coroutine again, which is dead, and this is presumably the issue internally (which I assume can be fixed with a simple if statement).
Workaround
Adding a coroutine.yield() at the end, which works as explained above because the wait tries to resume the coroutine again, but it’s yielded, not dead.
Issue Area: Engine Issue Type: Other Impact: Low Frequency: Constantly
This seems like expected behavior to me, you’re resuming a thread which is already scheduled for resumption by the engine scheduler. Not throwing this error could lead to situations where a thread is scheduled for resumption but the engine fails silently because some other part of your code unexpectedly resumed it.
You can solve this in a fairly trivial way:
function foo()
local thread = coroutine.running()
local resumed = false
local function resume(...)
if not resumed then
resumed = true
task.spawn(thread, ...)
end
end
task.delay(5, resume, false)
task.spawn(function ()
-- do something which yields
resume(true)
end)
local interrupted = coroutine.yield()
print("Wait interrupted:", interrupted)
end
At the end of the day, you shouldn’t be trying to resume a thread which you’ve already told the scheduler to resume. This will only lead to race-conditions and conflicts between the two systems that try to resume the thread.
Agreed that it’s a bad idea to resume it anyway. However, this silent nil error seems quite obscure. It should be a clear error, including a traceback, saying something like “tried to resume coroutine twice”