Studio won't correctly complete BindToClose and PlayerRemoving

Reproduction Steps

  1. Run this script:
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()
  1. Press the “Stop” button
  2. You’ll get:
SERVER PlayerRemoving
  SERVER BindToClose
  *** end BindToClose
  1. This means that PlayerRemoving was interrupted
  2. Run it again
  3. In the command bar run:
game.Players.LocalPlayer:Kick()
  1. This will run PlayerRemoving entirely:
  SERVER PlayerRemoving
  PlayerRemoving 1
  PlayerRemoving 2
  PlayerRemoving 3
  PlayerRemoving 4
  PlayerRemoving 5
  *** end PlayerRemoving
  1. But will NOT run BindToClose, UNTIL you press “Leave” button:
    eLV1CimSps
  SERVER BindToClose
  *** end BindToClose
  1. 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)
  1. Run
  2. Now all instructions will correctly:
  PlayerRemoving 1
  BindToClose 1
  PlayerRemoving 2
  BindToClose 2
  PlayerRemoving 3
  BindToClose 3
  PlayerRemoving 4
  BindToClose 4
  PlayerRemoving 5
  *** end PlayerRemoving
  BindToClose 5
  *** end BindToClose

… and here is the most important:

  1. Set a breakpoint on the last line (print())
  2. Run
  3. Stop
  4. Now it will freeze for 30 seconds and will only print:
 SERVER BindToClose

… which means PlayerRemoving is not running when it stops the game after a breakpoint (or after an error line).

Expected Behavior
PlayerRemoving and BindToClose should run correctly in ALL cases, as shown in item 11 above.

Actual Behavior
In each case above, it will be a different behavior

Issue Area: Studio
Issue Type: Freezing
Impact: High
Frequency: Constantly

7 Likes

Studio overall is a total mess:

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

8 Likes

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?

1 Like

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.

2 Likes

Thanks for the report! We will follow up when we have an update for you.

7 Likes

Yeah, literally, please fix it. When I play test my game the leaderstats won’t load causing loads of client scripts to error.

2 Likes

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.

2 Likes

This has not changed to this day and probably never will.
I was forced to create a series of internal controls to overcome this bug.

1 Like

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.

2 Likes

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.

2 Likes

Hey everyone, calling in the troops to get this fixed. So sorry for the delay.

3 Likes

I didn’t get it.


2 Likes

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:

  1. PlayerRemoving callbacks are not run to completion when stopping the Studio session. In particular when there are yields inside the callback.
  2. PlaySolo does not run BindToClose unless you click “Leave” despite the last player being kicked.
  3. 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!

2 Likes

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:

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

11 Likes

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

1 Like

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.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.