Handling Signals in Heroku
During dyno shutdown
Heroku sends SIGTERM
to all processes on the machine, not just the ones
defined in the Procfile
.
This has a few consequences, if your processes do not handle SIGTERM
as a
graceful shutdown you can’t change the configured signal like you can with
systemd
’s
KillSignal
and Docker’s
STOPSIGNAL
.
So if you’re running NGINX which uses SIGQUIT
for graceful shutdown, you’ll
need to recompile NGINX with a
patch to change
the shutdown signals. This is true even if you’re using the Heroku maintained
NGINX buildpack. Celery has a similar issue with Heroku that can be
mitigated with the REMAP_SIGTERM
env
var.
Additionally, by sending signals to every process on the machine, you can’t
have a parent process trap and change the signals that get passed down to the
child, which would avoid the NGINX recompile. And since every process gets
SIGTERM
ed, both parent and worker processes need to handle SIGTERM
as
a graceful shutdown request.
Heroku’s “send signals to all the processes” approach is similar to the
default KillMode=crontrol-group
setting described in the systemd
docs.
Which works for some cases, but services like NGINX would be better off with
KillMode=mixed
and KillSignal=SIGQUIT
.
Conclusion
Heroku is easy to get started with but lacks some basic configuration settings that are helpful for robust process management.