Fix non-graceful server shutdowns and improve signal handling #41
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.
This fixes the server not gracefully shutting down when using
docker compose down
/docker compose restart
due to SIGINT being ignored byos.system()
.The script will gracefully shutdown with with both SIGINT and SIGTERM. This PR does not modify the Dockerfile, so SIGINT remains the default stop signal.
When a SIGINT or SIGTERM is first received, the script will send SIGINT to the Reforger process and wait for it to exit. The subprocess will be killed if a second interrupt is sent, although in practice this won't matter since SIGKILL is sent when Docker times out.
The script will also pass-through the Reforger process's exit code unless it is killed by the script, in which case it will exit with code 1.
As a side effect of passing an argument list to
subprocess.Popen
, command injection is no longer possible through the environment variablesARMA_BINARY
,ARMA_MAX_FPS
,ARMA_PROFILE
, orARMA_WORKSHOP_DIR
. TheARMA_PARAMS
variable can still be used to pass custom arguments.shlex.join()
is now used when printing the server command, which may result in slightly different outputs.Context
I had set up a server using this project's image and was planning to run
docker compose restart
periodically via cron jobs. However, when I tested the command, the logs would not show any indication of it shutting down and it would consistently exceed Docker's default timeout of 10 seconds before being killed. I increased this to 120s with the same results.Bacon informed me that the script may not be passing down SIGINT to Reforger, so I looked in
launch.py
for clues and foundos.system()
. It's documentation didn't mention anything about SIGINT, but I coincidentally came across this in the subprocess docs:I looked at the Dockerfile and saw it used
STOPSIGNAL SIGINT
, which is how I realized what was causing the issue. I later verified this behaviour with these test scripts, albeit on Python 3.12 and not 3.9 as used by Debian Bullseye.I've updated my server to use the following image:
From preliminary testing,
docker compose restart
now gracefully shuts down the server, although it had gotten close to the 10s timeout.P.S. I could not get ghcr.yaml's test job to work on my fork as it kept hanging on
steam-query.py
without any output.