How do you completely kill a thread?

There is no way to kill a running coroutine, they are automatically dead once they code inside of them has been ran completely, once dead they also cannot be restarted, the main purpose of a coroutine is to create a new thread so that loops can run in parallel while being in the same script

1 Like

I know what that does. But error is a built in function, and there’s simply no other way.

I was asking “how do you completely kill a thread”, and specified that it was to avoid a bunch of “if checks” all over the place (such as comparing returns to see if a player is occupied or not).
Please understand that it is INCREDIBLY frustrating to get non-answers such as “use returns” after saying that I don’t want to use returns for this case.
I understand that you don’t believe that there is a way to do this, and there very well may not be, but you could’ve just told me “I don’t think there’s a way to do this” to begin with instead of giving me an answer that, to me, makes me feel like you barely skimmed the question, and gave the most basic help to a completely different problem.

Anyways, I just wanted to explain why I got impatient. I’ll try to post some sort of suggestion since roblox is working on their own version of lua now, so they could probably implement a “soft error” feature. At least I hope so, since this could be very useful, not just in this case.

1 Like

Okay, make sure to send the link to it since I’ll upvote!

My rank isn’t high enough to post it. I think they changed the post approval process, cause I can’t find a way to post it. If you’re high enough rank to post in engine suggestions, could you do it for me?

Sure! I will do it right now, and when I do so, I will send you the link.

you could yield it like they said (removes functionality, think of this as putting a file in the garbage bin) then set the thread variable to nil (removing reference, destroying it). From there call gcinfo(“collect”) (tell the garbage collector to immediately get rid of it) to instantly start the garbage collection.

Hey, I know it’s been a while so sorry for the necrobump, but incase you or anyone else might still need this, here’s the method I use for killing running threads in my OOP modules:

local Class = {}
Class.__index = Class

function Class:Stop()
	local Table = {}                        --//new table
	for Index, Value in pairs(Class) do     --//begin cloning everything from our class to the new table
		if type(Value) == "function" then   --//if [value] is a function then
			Table[Index] = function()       --//set that function to return a coroutine.yield()
				coroutine.yield()
			end
		else                                --//if not a function then
			Table[Index] = Value            --//set the index to it's normal value
		end
	end
	Table.__index = Table                   --//overwrite the __index from the original class to our table
	setmetatable(self, Table)               --//replace the class metatable with our table
end

return Class
Here is a quick example on one of it's use cases:
--//Modulescript
local Class = {}
Class.__index = Class

function Class.new()
	return setmetatable({}, Class)
end

function Class:Stop()
	local Table = {}                        --//new table
	for Index, Value in pairs(Class) do     --//begin cloning everything from our class to the new table
		if type(Value) == "function" then   --//if [value] is a function then
			Table[Index] = function()       --//set that function to return a coroutine.yield()
				coroutine.yield()
			end
		else                                --//if not a function then
			Table[Index] = Value            --//set the index to it's normal value
		end
	end
	Table.__index = Table                   --//overwrite the __index from the original class to our table
	setmetatable(self, Table)               --//replace the class metatable with our table
end

function Class:SayHello()
	print("hi")
end

function Class:DoSomething()
	while true do
		self:SayHello()
		task.wait(1)
	end
end

return Class
--//Server script
local Class = require()      --//path to module

local NewClass = Class.new() --//create new class

task.spawn(function() 
	task.wait(5)             --//wait 5 seconds
	NewClass:Stop()          --//stop
end) 

NewClass:DoSomething()       --//example function

The stop function can be called from any script as long as it has the same NewClass object, so you can ignore the task.spawn() as I only used it in this example for simplicity’s sake. (And you wouldn’t be able to call NewClass:Stop() until after the example function finished lol)

Disclaimers: at least from my testing, this method will indeed work even when the function is not being run inside a coroutine/task.spawn environment. The running thread will also only be terminated once your code uses a class inherited function, but that should be often enough, else what would be the point of using OOP. Also, I haven’t done too much research on the topic, but I am pretty sure that lua will automatically garbage collect suspended threads if there are no strong references to them left, so I personally wouldn’t worry about memory leaks too much.

You can create the table with the replaced functions outside of the :Stop() function and keep it in memory and not have to recreate it everytime, but I keep it as is since doing the latter can be pretty messy in my opinion.

My original code for this was inspired by the snippet @FieryEvent posted in Coroutine.kill implementation - #15 by FieryEvent

6 Likes

Sorry for yet another bump, but hopefully this should mark this thread as closed. Not sure when it was released, but coroutine.close does exactly what you need! As an alternative, you can also use task.cancel if you want your thread to be managed by the task scheduler, but this means you’ll have to create the thread using something like task.spawn not coroutines.

4 Likes