Reproduction Steps
The following snippet of code reproduces the bug:
local thread = coroutine.create(function(...)
task.wait()
return nil -- nil can be anything, as long as there is at least one result
end)
coroutine.resume(thread)
task.wait(1)
print(coroutine.status(thread)) -- suspended
This snippet also reproduces the issue (function was run by the task scheduler, initiated by task.spawn
, and returned more than one result):
local thread
task.spawn(function()
thread = coroutine.running()
return 123
end)
task.wait(1)
print(coroutine.status(thread)) -- suspended
The thread will remain suspended
, despite having very clearly exited. The results can be printed out from coroutine.resume
, and thus the thread has very blatantly exited and returned and should be dead
. However this is not the case at all, the function remains in a suspended
state. Seemingly the thread remains in memory without ever garbage collecting, though I am not sure if my testing was very accurate.
The following snippet does not reproduce this issue (no return results, no bug):
local thread = coroutine.create(function(...)
task.wait()
return -- This return can be omitted, I figured that keeping things as close to the repro snippet would be beneficial
end)
coroutine.resume(thread)
task.wait(1)
print(coroutine.status(thread)) -- dead (no return results)
In summary:
- Any thread resumed or started by the task scheduler will not become
dead
after returning, given that the body function of the thread has more at least one return result. - If the thread has no return results it will become
dead
. - This effects all
task
functions including resumptions fromtask.wait
. - It is relevant to note that ModuleScript bodies must return a result so assuming they rely on the same scheduling mechanism, this bug likely affects all loaded ModuleScripts.
P.s. I have marked the status of this bug as âhighâ because I rely on thread statuses to determine when some user-entered code exits (and this bug consistently prevents me from detecting that), as well as this seemingly resulting in a memory leak. I apologize if this is an incorrect way to mark this issue, I wasnât entirely sure.
Expected Behavior
Any thread resumed by the task scheduler which exits should have a dead
status regardless of what it returns.
Actual Behavior
Any thread resumed by the task scheduler which has one or more return results will remain in a suspended
status indefinitely, and never GC.
Issue Area: Engine
Issue Type: Other
Impact: High
Frequency: Constantly