local Players = game:GetService("Players")
Players.PlayerRemoving:Connect(function(Player)
print("SERVER PlayerRemoving")
for i=1, 5 do
wait(1)
print('PlayerRemoving', i)
end
print("*** end PlayerRemoving")
end)
game:BindToClose(function()
print("SERVER BindToClose")
--for i=1, 5 do -- Intentionally commented on first tests
-- wait(1)
-- print('BindToClose', i)
--end
print('*** end BindToClose')
end)
print()
Press the “Stop” button
You’ll get:
SERVER PlayerRemoving
SERVER BindToClose
*** end BindToClose
This means that PlayerRemovingwas interrupted
Run it again
In the command bar run:
game.Players.LocalPlayer:Kick()
This will run PlayerRemoving entirely:
SERVER PlayerRemoving
PlayerRemoving 1
PlayerRemoving 2
PlayerRemoving 3
PlayerRemoving 4
PlayerRemoving 5
*** end PlayerRemoving
But will NOT run BindToClose, UNTIL you press “Leave” button:
SERVER BindToClose
*** end BindToClose
Uncomment the for loop inside BindToClose:
game:BindToClose(function()
print("SERVER BindToClose")
for i=1, 5 do
wait(1)
print('BindToClose', i)
end
print('*** end BindToClose')
end)
When clicking Play sometimes the client will load before the server.
Testing the game with more players using the Local Server feature has a ton of issues. A lot of things will error, not load, and other things.
Stopping the game like shown in this post doesn’t trigger PlayerRemoving sometimes and is just horrible. The only way to go around it is by kicking yourself out.
Things replicate without order at the very start of the game, and it even has delays in replication. (Parenting an object and then setting an attribute to true, the attribute will be replicated first than all the descendants of the object)
If the last one is expected, please one of those Roblox staff that comes around reading reports, answer it if possible.
It’s a good feature that the Studio won’t allow you to yield too much in the function connected to PlayerRemoving signal.
Stop means stop. Stop the server, stop the client. How would you stop it when you accidentaly inserted an infinitely-yielding script inside of this function?
In this case, it is a matter of interpretation. For me, STOP is closing the game naturally, that is, executing everything that should be executed as if it were in Roblox Player, as in this case BindToClose and PlayerRemoving.
To force an interruption of the entire process, it should have an ABORT button, which would be the most appropriate term in terms of IT.
Besides that, there is an incorrect freeze which I mentioned starting in item 12.
This thread fundamentally misunderstands how Studio handles game shutdowns and player kicking.
Before I start anything,
In my honest opinion, it should not be possible for a breakpoint to trigger inside a BindToClose callback, given the 30s timer
It should raise an error stating Cannot break code in a BindToClose callback
When you press Stop, PlayerRemoving will run until it yields, but the thread is never resumed, unless a BindToClose callback yields, when BindToClose completes, Studio will kill the server, not resuming any yielded threads, which includes PlayerRemoving
If BindToClose and PlayerRemoving both have repeating yields in them, as mentioned by the OP, you notice an effect where both members start trading thread ownership. Remember, Luau is not multithreaded, as stated before this is the case until BindToClose completes
Player:Kick will not invoke BindToClose because the server is still running.
Why do you mark these bug reports as solved if they are not fixed? All it does is mislead people seeing a checkmark next to the title in the home screen.
As I considered in the previous post, using a saying “if a problem has no solution, it is solved”…
Of course there is a solution, but since Roblox has commonly neglected bugs for years, and since I created my own solution to overcome this bug, I took it as done.
But you’re right. Reopened the bug report.
Hey! Just wanted to update you on where we’re at. I’ve had a look at the issues you’ve mentioned and of the 3:
PlayerRemoving callbacks are not run to completion when stopping the Studio session. In particular when there are yields inside the callback.
PlaySolo does not run BindToClose unless you click “Leave” despite the last player being kicked.
Setting a breakpoint on the last line then Stopping the session will freeze Studio for 30 seconds.
For the first point a previous comment discusses the reasons well. We cannot guarantee that yields in PlayerRemoving callbacks will be respected.
For the second I’ll mention that PlaySolo is a simulation and we cannot emulate 100% Server behavior through Studio and this is an unfortunate consequence.
For the third point however we agree this is a bug and we’re looking into it. Will update this thread when we’ve got more to share!
This is such an old topic that I even forgot about it, because I was forced to create a “homemade solution” for this problem and, in this way, I managed to overcome this bug.
My solution is obviously much more complex than the example below, but the basic idea is:
In PlayerRemoving, on the last line (after doing everything you need to do), create a flag indicating that you can now execute BindToClose. Ex:
local CanCloseServer = false
Players.PlayerRemoving:Connect(function(Player)
-- here all code you need on PlayerRemoving
-- ...
CanCloseServer = true -- last line
end)
In BindToClose, loop until the PlayerRemoving has completed:
game:BindToClose(function()
while RunService:IsRunning() and not CanCloseServer do
task.wait()
end
-- here all code you need on BindToClose
-- ...
end)
This will force BindToClose to only be executed after PlayerRemoving has been completely executed.
Glad to hear you’ve got a workaround. I just want to point out, just in case, the 30 second timeout for BindToClose after which we would shutdown regardless as mentioned in the documentation of BindToClose
Since I’m sure this bug won’t be fixed by Roblox and at the same time as I’ve already created a workaround that solves the problem, I’ll close this thread.