mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
parent
6ed6b1399e
commit
e106bf82a8
28
NOTICE
28
NOTICE
@ -54,6 +54,34 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
gunicorn.reloader
|
||||
-----------------
|
||||
|
||||
Based on greins.reloader module under MIT license:
|
||||
|
||||
2010 (c) Meebo, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
doc/sitemap_gen.py
|
||||
------------------
|
||||
Under BSD License :
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
|
||||
def on_starting(server):
|
||||
# use server hook to patch socket to allow worker reloading
|
||||
from gevent import monkey
|
||||
monkey.patch_socket()
|
||||
|
||||
def when_ready(server):
|
||||
def monitor():
|
||||
modify_times = {}
|
||||
while True:
|
||||
for module in sys.modules.values():
|
||||
path = getattr(module, "__file__", None)
|
||||
if not path: continue
|
||||
if path.endswith(".pyc") or path.endswith(".pyo"):
|
||||
path = path[:-1]
|
||||
try:
|
||||
modified = os.stat(path).st_mtime
|
||||
except:
|
||||
continue
|
||||
if path not in modify_times:
|
||||
modify_times[path] = modified
|
||||
continue
|
||||
if modify_times[path] != modified:
|
||||
logging.info("%s modified; restarting server", path)
|
||||
os.kill(os.getpid(), signal.SIGHUP)
|
||||
modify_times = {}
|
||||
break
|
||||
gevent.sleep(1)
|
||||
|
||||
import gevent
|
||||
gevent.spawn(monitor)
|
||||
@ -706,6 +706,21 @@ class Debug(Setting):
|
||||
"""
|
||||
|
||||
|
||||
class Reload(Setting):
|
||||
name = "reload"
|
||||
section = 'Debugging'
|
||||
cli = ['--reload']
|
||||
validator = validate_bool
|
||||
action = 'store_true'
|
||||
default = False
|
||||
desc = '''\
|
||||
Restart workers when code changes.
|
||||
|
||||
This setting is intended for development. It will cause workers to be
|
||||
restarted whenever application code changes.
|
||||
'''
|
||||
|
||||
|
||||
class Spew(Setting):
|
||||
name = "spew"
|
||||
section = "Debugging"
|
||||
|
||||
54
gunicorn/reloader.py
Normal file
54
gunicorn/reloader.py
Normal file
@ -0,0 +1,54 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
|
||||
|
||||
class Reloader(threading.Thread):
|
||||
def __init__(self, extra_files=None, interval=1, callback=None):
|
||||
super(Reloader, self).__init__()
|
||||
self.setDaemon(True)
|
||||
self._extra_files = set(extra_files or ())
|
||||
self._extra_files_lock = threading.RLock()
|
||||
self._interval = interval
|
||||
self._callback = callback
|
||||
|
||||
def add_extra_file(self, filename):
|
||||
with self._extra_files_lock:
|
||||
self._extra_files.add(filename)
|
||||
|
||||
def get_files(self):
|
||||
fnames = [
|
||||
re.sub('py[co]$', 'py', module.__file__)
|
||||
for module in sys.modules.values()
|
||||
if hasattr(module, '__file__')
|
||||
]
|
||||
|
||||
with self._extra_files_lock:
|
||||
fnames.extend(self._extra_files)
|
||||
|
||||
return fnames
|
||||
|
||||
def run(self):
|
||||
mtimes = {}
|
||||
while True:
|
||||
for filename in self.get_files():
|
||||
try:
|
||||
mtime = os.stat(filename).st_mtime
|
||||
except OSError:
|
||||
continue
|
||||
old_time = mtimes.get(filename)
|
||||
if old_time is None:
|
||||
mtimes[filename] = mtime
|
||||
continue
|
||||
elif mtime > old_time:
|
||||
if self._callback:
|
||||
self._callback(filename)
|
||||
time.sleep(self._interval)
|
||||
@ -12,6 +12,7 @@ import traceback
|
||||
|
||||
from gunicorn import util
|
||||
from gunicorn.workers.workertmp import WorkerTmp
|
||||
from gunicorn.reloader import Reloader
|
||||
from gunicorn.http.errors import InvalidHeader, InvalidHeaderName, \
|
||||
InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion, \
|
||||
LimitRequestLine, LimitRequestHeaders
|
||||
@ -79,6 +80,14 @@ class Worker(object):
|
||||
loop is initiated.
|
||||
"""
|
||||
|
||||
# start the reloader
|
||||
if self.cfg.reload:
|
||||
def changed(fname):
|
||||
self.log.info("Worker reloading: %s modified", fname)
|
||||
os.kill(self.pid, signal.SIGTERM)
|
||||
raise SystemExit()
|
||||
Reloader(callback=changed).start()
|
||||
|
||||
# set enviroment' variables
|
||||
if self.cfg.env:
|
||||
for k, v in self.cfg.env.items():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user