Advanced Thread Termination Question

So this is a very simple example trying to show a very advanced concept/problem. It is needed as part of a script utility library I am writing. I need a script (thread) to be able to indirectly terminate its own thread immediately (and possibly unknowingly) from another script or modulescript without infinite wait statements or any clunky solutions.

As you may know, a script cannot terminate itself simply with a script:Destroy() or script.Disabled=true statement. Only another script/thread may do this. The use of BindableFunctions and/or coroutines should accomplish this, especially considering the definition is in another script enitirely.

workspace.DefineScript:

local stop = Instance.new("BindableFunction",workspace);stop.Name = "Stop";
function stop.OnInvoke(scr)
	coroutine.wrap(function() 
		scr:Destroy()
		print (scr,"Destroyed!")
	end)()
end

workspace.TerminateMe:

wait(3)
workspace.Stop:Invoke(script)
while wait(3) do
	print("But I am still alive")
end

Output:
11:41:38.065 TerminateMe Destroyed! - Server - DefineScript:5
11:41:41.079 But I am still alive (x7) - Studio

So yeah, this is a big problem… the script runs perpetually without being parented, which will slow down the game if done hundreds of times and the orphaned code itself could be doing unintended things to other parts of the game.

But I am baffled why this is not working! BindableFunction alone should create a new thread (or use the DefineScript thread) which could easily then terminate the other thread. And then coroutine.wrap should also create a new thread not associated with TerminateMe. So what gives? I’m hoping one of you experts can figure this one out!

This is a bit difficult to solve

Destroying modulescripts wont stop their termination, a workaround could be using debounces or to constantly make the loops in the script check if the script still exists and if not then to break the loops.

But if your concerned about performance then I question if debounces would be a viable solution. And checking if the script exists in loops is much more resource expensive.

You might be able to get something out of this thread

It isn’t a ModuleScript in this case but I did find a solution I am ok with…

workspace.DefineScript

local stop = Instance.new("BindableFunction",workspace);stop.Name = "Stop";
function stop.OnInvoke(scr)
	wait() -- This yield seems to make all the difference
	scr:Destroy()
	print (scr,"Destroyed!")
end

This is good enough because the calling thread can’t continue as it is waiting for the Stop BindableFunction to return a result, and will likely be terminated before it gets its answer. The magic happens in the wait() statement, as the old thread relinquishes control to a new/other thread.