switch QUIT and TERM signal

With this change, when gunicorn receives a QUIT all the workers are
killed immediately and exit and TERM is used for the graceful shutdown.

Note: the old behaviour was based on the NGINX but the new one is more
correct according the following doc:

https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html

also it is complying with the way the signals are sent by heroku:

https://devcenter.heroku.com/articles/python-faq#what-constraints-exist-when-developing-applications-on-heroku
This commit is contained in:
benoitc 2014-03-08 17:07:35 -08:00
parent 24a060ed02
commit 81241907ff
4 changed files with 17 additions and 17 deletions

View File

@ -12,8 +12,8 @@ exception of TTIN/TTOU the signals handling match the behaviour of `nginx
Master process
==============
- **TERM**, **INT**: Quick shutdown
- **QUIT**: Graceful shutdown. Waits for workers to finish their
- **QUIT**, **INT**: Quick shutdown
- **TERM**: Graceful shutdown. Waits for workers to finish their
current requests up to the *graceful timeout*.
- **HUP**: Reload the configuration, start the new worker processes with a new
configuration and gracefully shutdown older workers. If the application is
@ -35,8 +35,8 @@ Sending signals directly to the worker processes should not normally be
needed. If the master process is running, any exited worker will be
automatically respawned.
- **TERM**, **INT**: Quick shutdown
- **QUIT**: Graceful shutdown
- **QUIT**, **INT**: Graceful shutdown
- **TERM**: Quick shutdown
- **USR1**: Reopen the log files
Reload the configuration
@ -94,16 +94,16 @@ processes will start to gracefully shut down.
t this point you can still revert to the old server because it hasn't closed its listen sockets yet, by following these steps:
- Send HUP signal to the old master process - it will start the worker processes without reloading a configuration file
- Send QUIT signal to the new master process to gracefully shut down its worker processes
- Send TERM signal to the new master process to force it quit
- Send TERM signal to the new master process to gracefully shut down its worker processes
- Send QUIT signal to the new master process to force it quit
If for some reason new worker processes do not quit, send KILL signal to
them After new master process quits, the old master process removes
them after the new master process quits, the old master process removes
.oldbin suffix from its .pid file, and everything is exactly as before
the upgrade attempt.
If an update is successful and you want to keep the new server, send
QUIT signal to the old master process to leave only new server
the TERM signal to the old master process to leave only new server
running::
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

View File

@ -222,8 +222,8 @@ class Arbiter(object):
self.log.info("Hang up: %s", self.master_name)
self.reload()
def handle_quit(self):
"SIGQUIT handling"
def handle_term(self):
"SIGTERM handling"
raise StopIteration
def handle_int(self):
@ -231,7 +231,7 @@ class Arbiter(object):
self.stop(False)
raise StopIteration
def handle_term(self):
def handle_quit(self):
"SIGTERM handling"
self.stop(False)
raise StopIteration

View File

@ -125,7 +125,7 @@ class Worker(object):
# init new signaling
signal.signal(signal.SIGQUIT, self.handle_quit)
signal.signal(signal.SIGTERM, self.handle_exit)
signal.signal(signal.SIGINT, self.handle_exit)
signal.signal(signal.SIGINT, self.handle_quit)
signal.signal(signal.SIGWINCH, self.handle_winch)
signal.signal(signal.SIGUSR1, self.handle_usr1)
# Don't let SIGQUIT and SIGUSR1 disturb active requests
@ -137,13 +137,13 @@ class Worker(object):
def handle_usr1(self, sig, frame):
self.log.reopen_files()
def handle_quit(self, sig, frame):
self.alive = False
def handle_exit(self, sig, frame):
self.alive = False
# worker_int callback
self.cfg.worker_int(self)
def handle_quit(self, sig, frame):
self.alive = False
sys.exit(0)
def handle_error(self, req, client, addr, exc):

View File

@ -30,9 +30,9 @@ class TornadoWorker(Worker):
web.RequestHandler.clear = clear
sys.modules["tornado.web"] = web
def handle_quit(self, sig, frame):
def handle_exit(self, sig, frame):
if self.alive:
super(TornadoWorker, self).handle_quit(sig, frame)
super(TornadoWorker, self).handle_exit(sig, frame)
self.stop()
def handle_request(self):