Your run_as user needs the reticulate R package installed, and a reticulate-compatible python environment (running reticulate::install_miniconda() is what I did).
Repro instructions
Run pgrep R before launching Shiny Server, hopefully there are no processes but if there are take note of them.
Launch Shiny Server.
Load the above app.
Do pgrep R again, see the new pid that has appeared.
Without closing the browser, stop Shiny Server.
Do pgrep R again, see that the new pid has not disappeared; i.e., the R process has leaked!
Explanation
This happens because Shiny Server's normal strategy for stopping R processes is by sending SIGINT, waiting 20 seconds, and sending SIGTERM if necessary. This works fine when the server is running normally. But during shutdown, SIGINT is sent but there isn't time for 20 seconds to pass to follow up with SIGTERM if necessary. In this case, something about using reticulate/python causes SIGINT signals to be ignored by the R process; but SIGTERM would have worked.
The fix is that when shiny-server is shutting down, it should be less polite and just send SIGTERM. (Note that there's no real-world evidence that SIGTERM is worse for Shiny apps than SIGINT, when I wrote this code many years ago it just seemed the right thing to do to simulate a user hitting Ctrl+C, so any tryCatch/finally could run--but RStudio Connect just sends SIGTERM and it doesn't seem to have been a problem for anyone.)
Install the following app under a subdirectory of
/srv/shiny-server/
:app.R
test.py
Prerequisites
Your run_as user needs the reticulate R package installed, and a reticulate-compatible python environment (running
reticulate::install_miniconda()
is what I did).Repro instructions
pgrep R
before launching Shiny Server, hopefully there are no processes but if there are take note of them.pgrep R
again, see the new pid that has appeared.pgrep R
again, see that the new pid has not disappeared; i.e., the R process has leaked!Explanation
This happens because Shiny Server's normal strategy for stopping R processes is by sending
SIGINT
, waiting 20 seconds, and sendingSIGTERM
if necessary. This works fine when the server is running normally. But during shutdown,SIGINT
is sent but there isn't time for 20 seconds to pass to follow up withSIGTERM
if necessary. In this case, something about using reticulate/python causesSIGINT
signals to be ignored by the R process; butSIGTERM
would have worked.The fix is that when shiny-server is shutting down, it should be less polite and just send
SIGTERM
. (Note that there's no real-world evidence thatSIGTERM
is worse for Shiny apps thanSIGINT
, when I wrote this code many years ago it just seemed the right thing to do to simulate a user hitting Ctrl+C, so any tryCatch/finally could run--but RStudio Connect just sendsSIGTERM
and it doesn't seem to have been a problem for anyone.)