How do you completely kill a thread?

Maybe just use return? I am pretty sure that kills a function/thread.

just the function/thread that is running

1 Like

Yeah. If you want something otherwise, create a bindablevent inside the module or the script, and fire it, and make every thread that you want to kill receive it, and use return on that thread when you receive the event.

maybe just create a bool variable, then make every function/thread check if the variable is true then everything will return. However this may create many wait loops

1 Like

With return:

local occupied = false
function step1()
	if occupied then return end
	--do stuff
	if not step2() then return end
	--do more stuff
end
function step2()
	if occupied then return end
	--do stuff
	if not step3 then return end
	--do more stuff
end
function step3()
	if occupied then return end
	--do stuff
end

With a thread being killed

function checkIfOccupied()
	if occupied  then
		--kill thread
	end
end
function step1()
	checkIfOccupied()
	step2()
end
function step2()
	checkIfOccupied()
	step3()
end
function step3()
	checkIfOccupied()
end

Like open up a baseplate and try using “error” instead of return. The entire thread of the original function ends. That means if “checkIfOccupied” kills the thread at step3, it kills the entire thread, meaning step3 gets halted, step2 gets halted and step1 gets halted. This can be done with an error put outputs garbage.

just make the checkoccupied return false if occupied, and then the other functions look if it’s false, then they just return nil and don’t run the other part.

That is precisely what I’m trying to avoid by having it kill the thread… I’m not looking for “how to make it work” I’m looking for how to avoid having five million if checks all embedded one in another and getting way out of hand if it can be simplified to 1 line.
If I need to check if it’s occupied, that’s fine, it’s just gonna get messy real fast when it’s inside an oop class where one function can lead to many other functions that all can possibly not work if occupied.

Well I am sorry, but that’s what you have to do.

It isn’t. I’ve already explained “error()” does this. I just want an alternative that doesn’t spam output.

As you can see return and break are the only ways, but return only works in functions:

Go in a game right now and run this code.

function Debug(str, str2)
	print(str)
	Debug2()
	print(str2)
end
function Debug2()
	if true then error() end
end
Debug(1, 2)

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.

2 Likes

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

7 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.

6 Likes