Repository navigation
[Bug] Deferrals held by one resource die when another resource listening to playerConnecting runs its GC #594
lilabyte
started this conversation in
[BUG] FiveM for GTAV Enhanced
Replies: 3 comments 1 reply
|
Hi, thanks this is fixed in the next patch. |
0 replies
|
Hello, |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
Ran into this while working on a connection queue. My queue resource calls
deferrals.defer()and then keeps the deferrals object around for as long as the player waits (in a cache), so it can keep callingdeferrals.update()and finallydeferrals.done(). That resource holds a reference the whole time, but if any other JS resource also listens toplayerConnecting, even one that never callsdeferrals.defer()and never touches the deferrals at all, the queue loses its deferrals as soon as that other resource's GC runs. Thedeferrals.update()anddeferrals.done()calls still go through on the server side without any error, but the client never gets them and just sits frozen on the last message it saw. Looks like when the other resource garbage collects its own unused copy of the deferrals functions, the callbacks get released for everyone, including the resource that is still holding and using them. If the other resource also keeps a reference to the deferrals, everything works fine. Stopping the other resource makes new connections work again, no need to restart the client or the server.Issue type
Server
Repro rate
Always
Server build version
FXServer-early-access b168 linux
OS
No response
CPU
No response
GPU
No response
RAM
No response
Storage type
None
Connection type
None
ISP and bandwidth
No response
DxDiag
No response
Network graph
No response
Platform
Linux
OS version / distribution
Debian 13
CPU
No response
RAM
No response
Using txAdmin?
Yes
Hosting provider
Self-hosted
Machine type
VPS
/perf endpoint output
No response
DDoS protection
No response
ulimit -n value (Linux only)
No response
Docker Compose file (Docker only)
No response
Steps to Reproduce
Two resources, and nothing else on the server listening to
playerConnecting.deferrals-holderholds every connection for 30 seconds and updates the message every second, then lets the player in:deferrals-holder/fxmanifest.luadeferrals-holder/server.jsdeferrals-bystanderonly listens toplayerConnectingand doesn't use the deferrals at all. The interval just throws away some memory every 250 ms so its GC runs all the time. Setting thebystander_retain_deferralsconvar totruemakes it keep the deferrals in an array:deferrals-bystander/fxmanifest.luadeferrals-bystander/server.jsThe bystander only uses GetConvar, nothing that touches the connection.
ensure deferrals-holderandensure deferrals-bystander.Holding the connection: N/30message, while the server console keeps printing[holder] update ...all the way to[holder] done.set bystander_retain_deferrals true(no restart needed, the convar is read on everyplayerConnecting) and connect again. Same allocations, but now every connection goes through fine, all 30 updates show up and you get in.Expected Behavior
A resource that only listens to
playerConnectingand never callsdeferrals.defer()shouldn't affect a resource that deferred the connection and is still holding the deferrals. Each resource dropping its own references to the deferrals shouldn't break them for the others, as long as some resource still holds them.Actual Behavior
The holder keeps its deferrals referenced for the whole 30 seconds (they live in the interval closure), so they are never garbage collected on its side. Still, once the bystander, which never called
deferrals.defer(), has its GC collect its unused copy of the deferrals, the holder'sdeferrals.update()anddeferrals.done()stop reaching the client. No errors anywhere, the server thinks everything worked, and the client stays stuck. Stopping the bystander makes the next connections work again, the client doesn't need a restart. With step 3 (bystander keeps the reference) it never happens, even with the GC running all the time, so it's not about load, it's about releasing those references.Evidence
No response
Additional Context
No response
All reactions