RunService.Stepped loop doesn't seem to Disconnect

Alright, maybe I’m being paranoid here but I’m a bit confused about how to stop a RunService loop using :Disconnect.
This is the code snipped I’m concerned with:

		task.spawn(function()
			local check
			print(check)
			check = RunS.Stepped:Connect(function()
				local current = RunS.Stepped:Wait()

				if (current - lastUpdate) > kd_expire then
					KD:Destroy()
					print(check)
					check:Disconnect()
				end

				print(check)
			end)
		end)

It’s basically a timer. If the value (KD) doesn’t get updated\changed within the time limit (kd_expire, 10 seconds) then the value is destroyed and the loop is supposed to end.

Now, the code works perfectly and gave me no problems. However, I’m worried about performance and possible memory leaks, especially since this is being done on the server. As you can see in the code, check is the loop “variable”. If I print check right after the variable is defined like this:

local check
print(check)

It’ll obviously print nil. Once check is assigned to the loop, it will print “Connection”, and so far it all makes sense. However, if I try to print check again after using check:Disconnect() inside the loop itself, it’ll still print “Connection” and not “nil”.
This is a bit weird and makes me wonder if the loop is still somehow running in the background, hence causing a possible memory leak?
Is there a better way to handle timed entities perhaps? As I said, the code works as intended and I might just be paranoid but I’m also trying to write better optimized code.

You could try using task.delay() to end the RunService.Heartbeat Connection and once the time given elapses, You can try checking it.

task.delay(10, function()
	KD:Destroy()
	check:Disconnect()
	KD = nil
	check = nil
end)

The problem is with your if statement,
if you minus variable current with variable lastUpdate then check if its greater than kd_expire then how will it makes sense?

instead of substracting it, add it.
Try

if (current + lastUpdate) > kd_expire then

Lets pretend current value is 10 and lastUpdate value is 5
and kd_expire value is 15

you are doing current - lastUpdate ( 10 - 5 )
then the answer will be 5 then you are checking if the 5 is greater than 15 (which is not possible)

That doesnt make the statement correct so it wont disconnect the connection.
try printing

print((current - lastUpdate) > kd_expire)

And it will return the result in false or true

MMh, I think this defeats the purpose of the timer?
The entity doesn’t last 10 seconds and that’s it. It can potentially last forever, as long as the value is updated within the 10 seconds limit. If you update it every 5 seconds for example, it won’t be destroyed, hence exist forever.

I might be misunderstanding but I think the logic in my code is correct for the purpose. As mentioned in the first post, the code works as intended, except the :Disconnect doesn’t seem to fire properly.

The current variable is updated every frame since it’s inside the RunService.Heartbeat loop, so it’ll be naturally bigger than lastUpdate
The variable lastUpdate (which also uses RunS.Stepped:Wait() to get the timeframe) is updated everytime the value is updated\changed (how many times do I have to say update? lol), so not every frame.

Also, everything inside this statement is run properly, so why shouldn’t it also run :Disconnect?

				if (current - lastUpdate) > kd_expire then
					KD:Destroy()
					print(check)
					check:Disconnect()
				end

Apologies for bumping this post, but it’s got pushed down quite a lot and I’d like some more opinions\feedbacks… :sweat_smile:

No memory leak here I believe. A connection is an object that gets garbage collected when there is no references to it. The reason it prints “connection” is because that variable still holds the connection object, since it references it. calling :Disconnect() does disconnect any connected functions to it, but it doesn’t remove the connection object itself. So I would make a change to this line

and add a check = nll at the end

Updated:

if (current - lastUpdate) > kd_expire then
	KD:Destroy()
	print(check)
	check:Disconnect()
    check = nil
end

Since now the connection is not referenced anymore, it will get garbage collected after a little time. No worries about it running in the background, once you do Disconnect() and nil any references to the connection, it’s gone.

If you still have doubt, before setting check to nil, try doing:
print(check.Connected)
and make sure it prints false. That means it has successfully disconnected.

Hope this helps!

1 Like

Thank you so much! I had no idea the .Connected property existed! I tried it and it’s prints False.
Also yeah, I’ll set check to nil, I tend to forget about garbage collection. :sweat_smile:

1 Like