DataModel.Close does not fire on DataModel closure

When testing on Studio, regardless of whether the script is running on the server or client, it does not appear to be firing the Close event, inherited from ServiceProvider.

Not sure whether this is intended or not; however, this behaviour is never documented anywhere, so I thought it would be worthwhile to report it so things could be cleared up.

Expected behavior

The DataModel.Close event, inherited from ServiceProvider should fire when the DataModel is closed, or simply, it should be documented that this should not be expected behaviour.


After some triaging with members of the community in this thread, we arrived at the following conclusions:

  • The event does fire; however, it only does when the Workspace SignalBehaviour property is not deferred.
  • Yielding inside the event just terminates its execution (likely since the TaskScheduler no longer runs the job responsible for resuming yielded threads)
  • The script at the point game.Close runs at appears to no longer exist (collected from memory?) despite upon running a GetChildren call inside of ServerScriptService the script was there just fine.

So it is likely something that perhaps slipped when deferred signals were implemented, I hope this helps :wink:

You’re supposed to use BindToClose, also you’re probably reffering to OnClose

The Close event doesn’t fire in client or edit mode—Roblox only sends that shutdown signal when a real server process stops (for example, when a server script uses game:BindToClose).

Supposed, yes. However, this does not exclude the engine having this behaviour and it being potentially incorrect. This is to report this as something to be looked at, not about whether it is good practice or not.

Also, no, please read the documentation if you are not sure what you will be talking about.

DataModel | Documentation - Roblox Creator Hub

image
Deprecated also means it won’t be maintained regardless of Engine updates


As for why Close is not marked as deprecated, I don’t know. I’d rather have it as a documentation issue

Yet again, I request you read instead of making incorrect assumptions.

While DataModel:BindToClose() is the officially supported API for server shutdown logic, the docs still list Close(): RBXScriptSignal under “Events inherited from ServiceProvider” with no deprecation notice. That means Close hasn’t been deprecated or removed—it’s simply not firing in Studio’s play/edit modes, which isn’t documented.

I have just tested it on Studio, and even after setting BindToClose it does not fire. Perhaps it is only on RCC instances; however, the key is that this issue is marked as a play-solo bug. It still creates cases where you can use the DataModel as the means of a ServiceProvider, but it does not behave properly as one.

Then it is an implementation issue for the Close event on the DataModel I assume, because then there is no reason to inherit from ServiceProvider if part of the methods and events it implements are broken/ missing/ not working.

Hm, if Close is inherited from ServiceProvider but doesn’t fire, that’s an implementation bug like you said, not a docs or practice issue.

  1. Could you share the exact script you’re using from the lines connecting Close and BindToClose
  2. Where you placed the script
  3. Your exact steps to reproduce
game:BindToClose(function() end)
game.Close:Connect(function() warn'hi' end)

Hi should be printed upon the server script being the ran and the game closing. It is a simple script on ServerScriptService, of course.

Simply run it and you will notice it does not warn hi on studio’s play test. I have not tested this on released places, so it could work there, however that is all I have on it.

1 Like
game:BindToClose(function()
    warn("BindToClose fired")
end)

game.Close:Connect(function()
    warn("Close fired")
end)

I used the script above to give me a better understanding.
Whenever I did a play solo test, neither warning appeared. However, when I did a server test , BindToClose fired and appears, but Close fired does not. I’d assume it’s likely an implementation bug because Close is not officially deprecated.

My studio version is 0.672.0.6720706

1 Like

If you put a task.wait inside :BindToClose does anything change? Personally my first guess is that the server is just shutting down before the .Close event can resume any connections

Amazingly enough: the issue appears to be related to deferred signals.

The .Close event will only fire on immediate because by the time the deferred signals fire, the DataModel and Luau state are likely already closed? Your suggestion helped me to jog a bit about it, however even if we wait inside of the BindToClose, the .Close event only appears to be fired after the script has been collected from memory and on immediate firing mode (The script collected from memory bit is because studio no longer recognizes where the warning is being issued from)

This also includes that yielding at any point inside of the .Close event will stop execution immediately. Likely since the Task Scheduler is no longer resuming yielded threads?


To summarise: .Close only fires when Immediate or AncestryDeferred firing is in effect; if Deferred firing is in effect, the event does not run. Likely because by the time the deferred signals fire, the state is already all cleaned up?

1 Like

So, in Studio’s Test Server the Close event is using Deferred firing mode, so by the time it actually dispatches the DataModel and Luau state have already been torn down, and any yields inside the handler are immediately canceled. BindToClose works because it always fires immediately. Given this, they either need to change Close to use Immediate firing for shutdown or at least document that it’s Deferred by default.

Yeah, something along those lines. You can test the behaviour by switching the SignalBehaviour to Immediate on the WorldRoot/ Workspace.


Anything but Deferred fires the event properly.

1 Like

Yeah, just tried this and you’re right. Reverting to deferred silences Close entirely.

1 Like