Repository navigation
fix(server): defer stopping a resource that is still running - #4403
Open
OneEarJoe5 wants to merge 1 commit into
Open
OneEarJoe5 wants to merge 1 commit into
OneEarJoe5 wants to merge 1 commit into
Conversation
`ExecuteCommand('restart ' .. GetCurrentResourceName())` (or stop /
ensure) tears down the runtime while the resource's own code is still
on the stack, which crashes the server once that code continues. This
happens for Lua and JS, from timers, ticks, events, commands and from
another resource that the resource called into.
Keep track of how often each resource is on the script runtime stack
(OnActivate / OnDeactivate) and, while it is, run stop, restart and
ensure for it on the next server tick instead, with the same principal
that issued the command. Everything else, including stopping or
restarting other resources and commands from the console, still runs
right away.
Signed-off-by: OneEarJoe5 <212275319+OneEarJoe5@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Goal of this PR
A resource that stops or restarts itself crashes the server, e.g.
ExecuteCommand('restart ' .. GetCurrentResourceName()).restartstops the resource right away, which destroys its runtime, and then the resource's own code that is still on the stack keeps running on freed state. That's #1421 (open since 2022, #1840 is a duplicate). It's not only JS: Lua does it too, and also the case where resource A calls an export of B and B restarts A.STOP_RESOURCEalready refuses to stop the calling resource, but thestop/restart/ensurecommands thatExecuteCommandreaches don't check anything.How is this PR achieving the goal
OnActivateand down onOnDeactivate, so it tells how often the resource is on the script runtime stack right now (same eventsResourceTimeWarningsand others already use).stop,restartandensure(only the stop+start part) check that counter. If the resource is running, the command is queued withgscomms_execute_callback_on_main_thread(..., true)and runs on the next server tick, after the resource's code has returned. So a self restart now just works instead of crashing.ExecuteCommandpushesresource.<name>), so ACE checks stay the same. A resource withoutcommand.restartstill getsAccess deniedand nothing is queued.This PR applies to the following area(s)
Server, ScRT: Lua, ScRT: JS
Successfully tested on
Platforms: Windows (server)
Server built from current master (5412ed8), with and without this change. Test resources: a JS resource that runs
restart/ensure/stopon itself from different places, a Lua resource doing the same, a Lua resource with an export that restarts the caller, and one that only gets restarted from outside. Each case in a fresh server.<cmd> <own resource>fromsetTimeout/setTick/ nodesetImmediate/ nodesetTimeoutSetTimeoutstopinstead ofrestart, same placesAlso checked:
GetResourceStateright after isstarted/stopped/started/startedlike before.restarttrying to restart itself:Access denied for command restart., resource keeps running, nothing queued.Couldn't restart resource ..., it's still running.once, nothing is queued again, and the server keeps going (console commands right after still work, no hitch warnings).The "before" column looks the same on the official Linux artifact 38621 (built from the same commit): every restart / ensure case crashes there too, and stop either crashes or leaves the resource half dead.
Not tested: a Linux build with this change (the logic doesn't touch anything platform specific).
Checklist
Fixes issues
fixes #1421