mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
fix whitespaces
This commit is contained in:
parent
8bf793d2e5
commit
f168a21dae
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import errno
|
||||
@ -20,7 +20,7 @@ class Application(object):
|
||||
An application interface for configuring and loading
|
||||
the various necessities for any given web framework.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, usage=None):
|
||||
self.usage = usage
|
||||
self.cfg = None
|
||||
@ -35,23 +35,23 @@ class Application(object):
|
||||
sys.stderr.write("\nError: %s\n" % str(e))
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def load_config(self):
|
||||
# init configuration
|
||||
self.cfg = Config(self.usage)
|
||||
|
||||
|
||||
# parse console args
|
||||
parser = self.cfg.parser()
|
||||
opts, args = parser.parse_args()
|
||||
|
||||
|
||||
# optional settings from apps
|
||||
cfg = self.init(parser, opts, args)
|
||||
|
||||
|
||||
# Load up the any app specific configuration
|
||||
if cfg and cfg is not None:
|
||||
for k, v in cfg.items():
|
||||
self.cfg.set(k.lower(), v)
|
||||
|
||||
|
||||
# Load up the config file if its found.
|
||||
if opts.config and os.path.exists(opts.config):
|
||||
cfg = {
|
||||
@ -67,7 +67,7 @@ class Application(object):
|
||||
print "Failed to read config file: %s" % opts.config
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
for k, v in cfg.items():
|
||||
# Ignore unknown names
|
||||
if k not in self.cfg.settings:
|
||||
@ -77,17 +77,17 @@ class Application(object):
|
||||
except:
|
||||
sys.stderr.write("Invalid value for %s: %s\n\n" % (k, v))
|
||||
raise
|
||||
|
||||
|
||||
# Lastly, update the configuration with any command line
|
||||
# settings.
|
||||
for k, v in opts.__dict__.items():
|
||||
if v is None:
|
||||
continue
|
||||
self.cfg.set(k.lower(), v)
|
||||
|
||||
|
||||
def init(self, parser, opts, args):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def load(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@ -95,12 +95,12 @@ class Application(object):
|
||||
self.do_load_config()
|
||||
if self.cfg.spew:
|
||||
debug.spew()
|
||||
|
||||
|
||||
def wsgi(self):
|
||||
if self.callable is None:
|
||||
self.callable = self.load()
|
||||
return self.callable
|
||||
|
||||
|
||||
def run(self):
|
||||
if self.cfg.spew:
|
||||
debug.spew()
|
||||
@ -111,11 +111,11 @@ class Application(object):
|
||||
os.setpgrp()
|
||||
except OSError, e:
|
||||
if e[0] != errno.EPERM:
|
||||
raise
|
||||
raise
|
||||
try:
|
||||
Arbiter(self).run()
|
||||
except RuntimeError, e:
|
||||
sys.stderr.write("\nError: %s\n\n" % e)
|
||||
sys.stderr.flush()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import imp
|
||||
@ -17,7 +17,7 @@ from gunicorn.app.base import Application
|
||||
ENVIRONMENT_VARIABLE = 'DJANGO_SETTINGS_MODULE'
|
||||
|
||||
class DjangoApplication(Application):
|
||||
|
||||
|
||||
def init(self, parser, opts, args):
|
||||
self.global_settings_path = None
|
||||
self.project_path = None
|
||||
@ -25,7 +25,7 @@ class DjangoApplication(Application):
|
||||
self.global_settings_path = args[0]
|
||||
if not os.path.exists(os.path.abspath(args[0])):
|
||||
self.no_settings(args[0])
|
||||
|
||||
|
||||
def get_settings_modname(self):
|
||||
from django.conf import ENVIRONMENT_VARIABLE
|
||||
|
||||
@ -69,7 +69,7 @@ class DjangoApplication(Application):
|
||||
os.pardir)))
|
||||
|
||||
return settings_modname
|
||||
|
||||
|
||||
def setup_environ(self, settings_modname):
|
||||
from django.core.management import setup_environ
|
||||
|
||||
@ -82,7 +82,7 @@ class DjangoApplication(Application):
|
||||
path = os.path.dirname(os.path.abspath(
|
||||
os.path.normpath(settings_mod.__file__)))
|
||||
sys.path.append(path)
|
||||
for part in parts[1:]:
|
||||
for part in parts[1:]:
|
||||
settings_mod = getattr(settings_mod, part)
|
||||
setup_environ(settings_mod)
|
||||
except ImportError:
|
||||
@ -101,9 +101,9 @@ class DjangoApplication(Application):
|
||||
from django.conf import settings
|
||||
from django.utils import translation
|
||||
translation.activate(settings.LANGUAGE_CODE)
|
||||
|
||||
|
||||
def validate(self):
|
||||
""" Validate models. This also ensures that all models are
|
||||
""" Validate models. This also ensures that all models are
|
||||
imported in case of import-time side effects."""
|
||||
from django.core.management.base import CommandError
|
||||
from django.core.management.validation import get_validation_errors
|
||||
@ -123,14 +123,14 @@ class DjangoApplication(Application):
|
||||
|
||||
def load(self):
|
||||
from django.core.handlers.wsgi import WSGIHandler
|
||||
|
||||
|
||||
self.setup_environ(self.get_settings_modname())
|
||||
self.validate()
|
||||
self.activate_translation()
|
||||
return WSGIHandler()
|
||||
|
||||
class DjangoApplicationCommand(DjangoApplication):
|
||||
|
||||
|
||||
def __init__(self, options, admin_media_path):
|
||||
self.usage = None
|
||||
self.cfg = None
|
||||
@ -139,16 +139,16 @@ class DjangoApplicationCommand(DjangoApplication):
|
||||
self.admin_media_path = admin_media_path
|
||||
self.callable = None
|
||||
self.project_path = None
|
||||
|
||||
|
||||
self.do_load_config()
|
||||
|
||||
for k, v in self.options.items():
|
||||
if k.lower() in self.cfg.settings and v is not None:
|
||||
self.cfg.set(k.lower(), v)
|
||||
|
||||
|
||||
def load_config(self):
|
||||
self.cfg = Config()
|
||||
|
||||
|
||||
if self.config_file and os.path.exists(self.config_file):
|
||||
cfg = {
|
||||
"__builtins__": __builtins__,
|
||||
@ -164,7 +164,7 @@ class DjangoApplicationCommand(DjangoApplication):
|
||||
print "Failed to read config file: %s" % self.config_file
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
for k, v in cfg.items():
|
||||
# Ignore unknown names
|
||||
if k not in self.cfg.settings:
|
||||
@ -174,7 +174,7 @@ class DjangoApplicationCommand(DjangoApplication):
|
||||
except:
|
||||
sys.stderr.write("Invalid value for %s: %s\n\n" % (k, v))
|
||||
raise
|
||||
|
||||
|
||||
for k, v in self.options.items():
|
||||
if k.lower() in self.cfg.settings and v is not None:
|
||||
self.cfg.set(k.lower(), v)
|
||||
@ -191,7 +191,7 @@ class DjangoApplicationCommand(DjangoApplication):
|
||||
settings_path = os.path.join(project_path, "settings.py")
|
||||
if not os.path.exists(settings_path):
|
||||
return self.no_settings(settings_path)
|
||||
|
||||
|
||||
if not settings_modname:
|
||||
project_name = os.path.split(project_path)[-1]
|
||||
settings_name, ext = os.path.splitext(
|
||||
@ -220,7 +220,7 @@ class DjangoApplicationCommand(DjangoApplication):
|
||||
def reload_django_settings(self, settings_modname):
|
||||
from django.conf import settings
|
||||
from django.utils import importlib
|
||||
|
||||
|
||||
mod = importlib.import_module(settings_modname)
|
||||
|
||||
# reload module
|
||||
@ -283,14 +283,14 @@ class DjangoApplicationCommand(DjangoApplication):
|
||||
|
||||
def load(self):
|
||||
from django.core.handlers.wsgi import WSGIHandler
|
||||
|
||||
|
||||
# reload django settings and setup environ
|
||||
self.setup_environ(self.get_settings_modname())
|
||||
|
||||
# validate models and activate translation
|
||||
self.validate()
|
||||
self.validate()
|
||||
self.activate_translation()
|
||||
|
||||
|
||||
from django.core.servers.basehttp import AdminMediaHandler, WSGIServerException
|
||||
|
||||
try:
|
||||
@ -308,7 +308,7 @@ class DjangoApplicationCommand(DjangoApplication):
|
||||
error_text = str(e)
|
||||
sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def run():
|
||||
"""\
|
||||
The ``gunicorn_django`` command line runner for launching Django
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import os
|
||||
@ -20,7 +20,7 @@ class PasterBaseApplication(Application):
|
||||
cx = loadwsgi.loadcontext(SERVER, self.cfgurl, relative_to=self.relpath)
|
||||
gc, lc = cx.global_conf.copy(), cx.local_conf.copy()
|
||||
cfg = {}
|
||||
|
||||
|
||||
host, port = lc.pop('host', ''), lc.pop('port', '')
|
||||
if host and port:
|
||||
cfg['bind'] = '%s:%s' % (host, port)
|
||||
@ -61,11 +61,11 @@ class PasterBaseApplication(Application):
|
||||
config_file = os.path.abspath(self.cfgfname)
|
||||
fileConfig(config_file, dict(__file__=config_file,
|
||||
here=os.path.dirname(config_file)))
|
||||
|
||||
|
||||
|
||||
|
||||
class PasterApplication(PasterBaseApplication):
|
||||
|
||||
|
||||
def init(self, parser, opts, args):
|
||||
if len(args) != 1:
|
||||
parser.error("No application name specified.")
|
||||
@ -81,14 +81,14 @@ class PasterApplication(PasterBaseApplication):
|
||||
|
||||
sys.path.insert(0, self.relpath)
|
||||
pkg_resources.working_set.add_entry(self.relpath)
|
||||
|
||||
|
||||
return self.app_config()
|
||||
|
||||
|
||||
def load(self):
|
||||
return loadapp(self.cfgurl, relative_to=self.relpath)
|
||||
|
||||
|
||||
class PasterServerApplication(PasterBaseApplication):
|
||||
|
||||
|
||||
def __init__(self, app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
|
||||
self.cfg = Config()
|
||||
self.app = app
|
||||
@ -127,7 +127,7 @@ class PasterServerApplication(PasterBaseApplication):
|
||||
def load_config(self):
|
||||
if not hasattr(self, "cfgfname"):
|
||||
return
|
||||
|
||||
|
||||
cfg = self.app_config()
|
||||
for k,v in cfg.items():
|
||||
try:
|
||||
@ -153,14 +153,14 @@ def run():
|
||||
def paste_server(app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs):
|
||||
"""\
|
||||
A paster server.
|
||||
|
||||
|
||||
Then entry point in your paster ini file should looks like this:
|
||||
|
||||
|
||||
[server:main]
|
||||
use = egg:gunicorn#main
|
||||
host = 127.0.0.1
|
||||
port = 5000
|
||||
|
||||
|
||||
"""
|
||||
from gunicorn.app.pasterapp import PasterServerApplication
|
||||
PasterServerApplication(app, gcfg=gcfg, host=host, port=port, *args, **kwargs).run()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import os
|
||||
@ -10,7 +10,7 @@ from gunicorn import util
|
||||
from gunicorn.app.base import Application
|
||||
|
||||
class WSGIApplication(Application):
|
||||
|
||||
|
||||
def init(self, parser, opts, args):
|
||||
if len(args) != 1:
|
||||
parser.error("No application module specified.")
|
||||
@ -29,4 +29,4 @@ def run():
|
||||
generic WSGI applications.
|
||||
"""
|
||||
from gunicorn.app.wsgiapp import WSGIApplication
|
||||
WSGIApplication("%prog [OPTIONS] APP_MODULE").run()
|
||||
WSGIApplication("%prog [OPTIONS] APP_MODULE").run()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from __future__ import with_statement
|
||||
@ -34,9 +34,9 @@ class Arbiter(object):
|
||||
WORKER_BOOT_ERROR = 3
|
||||
|
||||
START_CTX = {}
|
||||
|
||||
|
||||
LISTENER = None
|
||||
WORKERS = {}
|
||||
WORKERS = {}
|
||||
PIPE = []
|
||||
|
||||
# I love dynamic languages
|
||||
@ -49,17 +49,17 @@ class Arbiter(object):
|
||||
(getattr(signal, name), name[3:].lower()) for name in dir(signal)
|
||||
if name[:3] == "SIG" and name[3] != "_"
|
||||
)
|
||||
|
||||
|
||||
def __init__(self, app):
|
||||
os.environ["SERVER_SOFTWARE"] = SERVER_SOFTWARE
|
||||
|
||||
self.setup(app)
|
||||
|
||||
|
||||
self.pidfile = None
|
||||
self.worker_age = 0
|
||||
self.reexec_pid = 0
|
||||
self.master_name = "Master"
|
||||
|
||||
|
||||
# get current path, try to use PWD env first
|
||||
try:
|
||||
a = os.stat(os.environ['PWD'])
|
||||
@ -70,7 +70,7 @@ class Arbiter(object):
|
||||
cwd = os.getcwd()
|
||||
except:
|
||||
cwd = os.getcwd()
|
||||
|
||||
|
||||
args = sys.argv[:]
|
||||
args.insert(0, sys.executable)
|
||||
|
||||
@ -80,27 +80,27 @@ class Arbiter(object):
|
||||
"cwd": cwd,
|
||||
0: sys.executable
|
||||
}
|
||||
|
||||
|
||||
def setup(self, app):
|
||||
self.app = app
|
||||
self.cfg = app.cfg
|
||||
self.log = self.cfg.logger_class(app.cfg)
|
||||
|
||||
|
||||
if 'GUNICORN_FD' in os.environ:
|
||||
self.log.reopen_files()
|
||||
|
||||
|
||||
self.address = self.cfg.address
|
||||
self.num_workers = self.cfg.workers
|
||||
self.debug = self.cfg.debug
|
||||
self.timeout = self.cfg.timeout
|
||||
self.proc_name = self.cfg.proc_name
|
||||
self.worker_class = self.cfg.worker_class
|
||||
|
||||
|
||||
if self.cfg.debug:
|
||||
self.log.debug("Current configuration:")
|
||||
for config, value in sorted(self.cfg.settings.iteritems()):
|
||||
self.log.debug(" %s: %s", config, value.value)
|
||||
|
||||
|
||||
if self.cfg.preload_app:
|
||||
if not self.cfg.debug:
|
||||
self.app.wsgi()
|
||||
@ -117,7 +117,7 @@ class Arbiter(object):
|
||||
self.init_signals()
|
||||
if not self.LISTENER:
|
||||
self.LISTENER = create_socket(self.cfg, self.log)
|
||||
|
||||
|
||||
if self.cfg.pidfile is not None:
|
||||
self.pidfile = Pidfile(self.cfg.pidfile)
|
||||
self.pidfile.create(self.pid)
|
||||
@ -128,7 +128,7 @@ class Arbiter(object):
|
||||
self.cfg.settings['worker_class'].get())
|
||||
|
||||
self.cfg.when_ready(self)
|
||||
|
||||
|
||||
def init_signals(self):
|
||||
"""\
|
||||
Initialize master signal handling. Most of the signals
|
||||
@ -152,7 +152,7 @@ class Arbiter(object):
|
||||
"Main master loop."
|
||||
self.start()
|
||||
util._setproctitle("master [%s]" % self.proc_name)
|
||||
|
||||
|
||||
self.manage_workers()
|
||||
while True:
|
||||
try:
|
||||
@ -163,18 +163,18 @@ class Arbiter(object):
|
||||
self.murder_workers()
|
||||
self.manage_workers()
|
||||
continue
|
||||
|
||||
|
||||
if sig not in self.SIG_NAMES:
|
||||
self.log.info("Ignoring unknown signal: %s", sig)
|
||||
continue
|
||||
|
||||
|
||||
signame = self.SIG_NAMES.get(sig)
|
||||
handler = getattr(self, "handle_%s" % signame, None)
|
||||
if not handler:
|
||||
self.log.error("Unhandled signal: %s", signame)
|
||||
continue
|
||||
self.log.info("Handling signal: %s", signame)
|
||||
handler()
|
||||
handler()
|
||||
self.wakeup()
|
||||
except StopIteration:
|
||||
self.halt()
|
||||
@ -185,7 +185,7 @@ class Arbiter(object):
|
||||
except SystemExit:
|
||||
raise
|
||||
except Exception:
|
||||
self.log.info("Unhandled exception in main loop:\n%s",
|
||||
self.log.info("Unhandled exception in main loop:\n%s",
|
||||
traceback.format_exc())
|
||||
self.stop(False)
|
||||
if self.pidfile is not None:
|
||||
@ -195,7 +195,7 @@ class Arbiter(object):
|
||||
def handle_chld(self, sig, frame):
|
||||
"SIGCHLD handling"
|
||||
self.wakeup()
|
||||
|
||||
|
||||
def handle_hup(self):
|
||||
"""\
|
||||
HUP handling.
|
||||
@ -205,16 +205,16 @@ class Arbiter(object):
|
||||
"""
|
||||
self.log.info("Hang up: %s", self.master_name)
|
||||
self.reload()
|
||||
|
||||
|
||||
def handle_quit(self):
|
||||
"SIGQUIT handling"
|
||||
raise StopIteration
|
||||
|
||||
|
||||
def handle_int(self):
|
||||
"SIGINT handling"
|
||||
self.stop(False)
|
||||
raise StopIteration
|
||||
|
||||
|
||||
def handle_term(self):
|
||||
"SIGTERM handling"
|
||||
self.stop(False)
|
||||
@ -227,7 +227,7 @@ class Arbiter(object):
|
||||
"""
|
||||
self.num_workers += 1
|
||||
self.manage_workers()
|
||||
|
||||
|
||||
def handle_ttou(self):
|
||||
"""\
|
||||
SIGTTOU handling.
|
||||
@ -245,7 +245,7 @@ class Arbiter(object):
|
||||
"""
|
||||
self.kill_workers(signal.SIGUSR1)
|
||||
self.log.reopen_files()
|
||||
|
||||
|
||||
def handle_usr2(self):
|
||||
"""\
|
||||
SIGUSR2 handling.
|
||||
@ -254,7 +254,7 @@ class Arbiter(object):
|
||||
deployment with the ability to backout a change.
|
||||
"""
|
||||
self.reexec()
|
||||
|
||||
|
||||
def handle_winch(self):
|
||||
"SIGWINCH handling"
|
||||
if os.getppid() == 1 or os.getpgrp() != os.getpid():
|
||||
@ -263,7 +263,7 @@ class Arbiter(object):
|
||||
self.kill_workers(signal.SIGQUIT)
|
||||
else:
|
||||
self.log.info("SIGWINCH ignored. Not daemonized")
|
||||
|
||||
|
||||
def wakeup(self):
|
||||
"""\
|
||||
Wake up the arbiter by writing to the PIPE
|
||||
@ -273,7 +273,7 @@ class Arbiter(object):
|
||||
except IOError, e:
|
||||
if e.errno not in [errno.EAGAIN, errno.EINTR]:
|
||||
raise
|
||||
|
||||
|
||||
def halt(self, reason=None, exit_status=0):
|
||||
""" halt arbiter """
|
||||
self.stop()
|
||||
@ -283,7 +283,7 @@ class Arbiter(object):
|
||||
if self.pidfile is not None:
|
||||
self.pidfile.unlink()
|
||||
sys.exit(exit_status)
|
||||
|
||||
|
||||
def sleep(self):
|
||||
"""\
|
||||
Sleep until PIPE is readable or we timeout.
|
||||
@ -303,12 +303,12 @@ class Arbiter(object):
|
||||
raise
|
||||
except KeyboardInterrupt:
|
||||
sys.exit()
|
||||
|
||||
|
||||
|
||||
|
||||
def stop(self, graceful=True):
|
||||
"""\
|
||||
Stop workers
|
||||
|
||||
|
||||
:attr graceful: boolean, If True (the default) workers will be
|
||||
killed gracefully (ie. trying to wait for the current connection)
|
||||
"""
|
||||
@ -357,11 +357,11 @@ class Arbiter(object):
|
||||
if old_address != self.cfg.address:
|
||||
self.LISTENER.close()
|
||||
self.LISTENER = create_socket(self.cfg, self.log)
|
||||
self.log.info("Listening at: %s", self.LISTENER)
|
||||
self.log.info("Listening at: %s", self.LISTENER)
|
||||
|
||||
# spawn new workers with new app & conf
|
||||
self.cfg.on_reload(self)
|
||||
|
||||
|
||||
# unlink pidfile
|
||||
if self.pidfile is not None:
|
||||
self.pidfile.unlink()
|
||||
@ -370,15 +370,15 @@ class Arbiter(object):
|
||||
if self.cfg.pidfile is not None:
|
||||
self.pidfile = Pidfile(self.cfg.pidfile)
|
||||
self.pidfile.create(self.pid)
|
||||
|
||||
|
||||
# set new proc_name
|
||||
util._setproctitle("master [%s]" % self.proc_name)
|
||||
|
||||
|
||||
# manage workers
|
||||
self.log.reopen_files()
|
||||
|
||||
self.manage_workers()
|
||||
|
||||
self.manage_workers()
|
||||
|
||||
def murder_workers(self):
|
||||
"""\
|
||||
Kill unused/idle workers
|
||||
@ -392,7 +392,7 @@ class Arbiter(object):
|
||||
|
||||
self.log.critical("WORKER TIMEOUT (pid:%s)", pid)
|
||||
self.kill_worker(pid, signal.SIGKILL)
|
||||
|
||||
|
||||
def reap_workers(self):
|
||||
"""\
|
||||
Reap workers to avoid zombie processes
|
||||
@ -418,7 +418,7 @@ class Arbiter(object):
|
||||
except OSError, e:
|
||||
if e.errno == errno.ECHILD:
|
||||
pass
|
||||
|
||||
|
||||
def manage_workers(self):
|
||||
"""\
|
||||
Maintain the number of workers by spawning or killing
|
||||
@ -432,7 +432,7 @@ class Arbiter(object):
|
||||
while len(workers) > self.num_workers:
|
||||
(pid, _) = workers.pop(0)
|
||||
self.kill_worker(pid, signal.SIGQUIT)
|
||||
|
||||
|
||||
def spawn_worker(self):
|
||||
self.worker_age += 1
|
||||
worker = self.worker_class(self.worker_age, self.pid, self.LISTENER,
|
||||
@ -470,11 +470,11 @@ class Arbiter(object):
|
||||
def spawn_workers(self):
|
||||
"""\
|
||||
Spawn new workers as needed.
|
||||
|
||||
|
||||
This is where a worker process leaves the main loop
|
||||
of the master process.
|
||||
"""
|
||||
|
||||
|
||||
for i in range(self.num_workers - len(self.WORKERS.keys())):
|
||||
self.spawn_worker()
|
||||
|
||||
@ -485,11 +485,11 @@ class Arbiter(object):
|
||||
"""
|
||||
for pid in self.WORKERS.keys():
|
||||
self.kill_worker(pid, sig)
|
||||
|
||||
|
||||
def kill_worker(self, pid, sig):
|
||||
"""\
|
||||
Kill a worker
|
||||
|
||||
|
||||
:attr pid: int, worker pid
|
||||
:attr sig: `signal.SIG*` value
|
||||
"""
|
||||
@ -504,4 +504,4 @@ class Arbiter(object):
|
||||
return
|
||||
except (KeyError, OSError):
|
||||
return
|
||||
raise
|
||||
raise
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import copy
|
||||
@ -34,21 +34,21 @@ def make_settings(ignore=None):
|
||||
return settings
|
||||
|
||||
class Config(object):
|
||||
|
||||
|
||||
def __init__(self, usage=None):
|
||||
self.settings = make_settings()
|
||||
self.usage = usage
|
||||
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name not in self.settings:
|
||||
raise AttributeError("No configuration setting for: %s" % name)
|
||||
return self.settings[name].get()
|
||||
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name != "settings" and name in self.settings:
|
||||
raise AttributeError("Invalid access!")
|
||||
super(Config, self).__setattr__(name, value)
|
||||
|
||||
|
||||
def set(self, name, value):
|
||||
if name not in self.settings:
|
||||
raise AttributeError("No configuration setting for: %s" % name)
|
||||
@ -77,7 +77,7 @@ class Config(object):
|
||||
worker_class.setup()
|
||||
return worker_class
|
||||
|
||||
@property
|
||||
@property
|
||||
def workers(self):
|
||||
return self.settings['workers'].get()
|
||||
|
||||
@ -85,15 +85,15 @@ class Config(object):
|
||||
def address(self):
|
||||
bind = self.settings['bind'].get()
|
||||
return util.parse_address(util.to_bytestring(bind))
|
||||
|
||||
|
||||
@property
|
||||
def uid(self):
|
||||
return self.settings['user'].get()
|
||||
|
||||
|
||||
@property
|
||||
def gid(self):
|
||||
return self.settings['group'].get()
|
||||
|
||||
|
||||
@property
|
||||
def proc_name(self):
|
||||
pn = self.settings['proc_name'].get()
|
||||
@ -112,17 +112,17 @@ class Config(object):
|
||||
logger_class.install()
|
||||
return logger_class
|
||||
|
||||
|
||||
|
||||
class SettingMeta(type):
|
||||
def __new__(cls, name, bases, attrs):
|
||||
super_new = super(SettingMeta, cls).__new__
|
||||
parents = [b for b in bases if isinstance(b, SettingMeta)]
|
||||
if not parents:
|
||||
return super_new(cls, name, bases, attrs)
|
||||
|
||||
|
||||
attrs["order"] = len(KNOWN_SETTINGS)
|
||||
attrs["validator"] = wrap_method(attrs["validator"])
|
||||
|
||||
|
||||
new_class = super_new(cls, name, bases, attrs)
|
||||
new_class.fmt_desc(attrs.get("desc", ""))
|
||||
KNOWN_SETTINGS.append(new_class)
|
||||
@ -135,7 +135,7 @@ class SettingMeta(type):
|
||||
|
||||
class Setting(object):
|
||||
__metaclass__ = SettingMeta
|
||||
|
||||
|
||||
name = None
|
||||
value = None
|
||||
section = None
|
||||
@ -147,11 +147,11 @@ class Setting(object):
|
||||
default = None
|
||||
short = None
|
||||
desc = None
|
||||
|
||||
|
||||
def __init__(self):
|
||||
if self.default is not None:
|
||||
self.set(self.default)
|
||||
|
||||
self.set(self.default)
|
||||
|
||||
def add_option(self, parser):
|
||||
if not self.cli:
|
||||
return
|
||||
@ -167,13 +167,13 @@ class Setting(object):
|
||||
if kwargs["action"] != "store":
|
||||
kwargs.pop("type")
|
||||
parser.add_option(*args, **kwargs)
|
||||
|
||||
|
||||
def copy(self):
|
||||
return copy.copy(self)
|
||||
|
||||
|
||||
def get(self):
|
||||
return self.value
|
||||
|
||||
|
||||
def set(self, val):
|
||||
assert callable(self.validator), "Invalid validator: %s" % self.name
|
||||
self.value = self.validator(val)
|
||||
@ -256,7 +256,7 @@ def validate_post_request(val):
|
||||
def _wrapped(instance, req, environ):
|
||||
return fun(instance, req)
|
||||
return _wrapped
|
||||
|
||||
|
||||
if not callable(val):
|
||||
raise TypeError("Value isn't a callable: %s" % val)
|
||||
|
||||
@ -279,9 +279,9 @@ class ConfigFile(Setting):
|
||||
default = None
|
||||
desc = """\
|
||||
The path to a Gunicorn config file.
|
||||
|
||||
|
||||
Only has an effect when specified on the command line or as part of an
|
||||
application specific configuration.
|
||||
application specific configuration.
|
||||
"""
|
||||
|
||||
class Bind(Setting):
|
||||
@ -293,11 +293,11 @@ class Bind(Setting):
|
||||
default = "127.0.0.1:8000"
|
||||
desc = """\
|
||||
The socket to bind.
|
||||
|
||||
|
||||
A string of the form: 'HOST', 'HOST:PORT', 'unix:PATH'. An IP is a valid
|
||||
HOST.
|
||||
"""
|
||||
|
||||
|
||||
class Backlog(Setting):
|
||||
name = "backlog"
|
||||
section = "Server Socket"
|
||||
@ -307,14 +307,14 @@ class Backlog(Setting):
|
||||
type = "int"
|
||||
default = 2048
|
||||
desc = """\
|
||||
The maximum number of pending connections.
|
||||
|
||||
The maximum number of pending connections.
|
||||
|
||||
This refers to the number of clients that can be waiting to be served.
|
||||
Exceeding this number results in the client getting an error when
|
||||
attempting to connect. It should only affect servers under significant
|
||||
load.
|
||||
|
||||
Must be a positive integer. Generally set in the 64-2048 range.
|
||||
|
||||
Must be a positive integer. Generally set in the 64-2048 range.
|
||||
"""
|
||||
|
||||
class Workers(Setting):
|
||||
@ -327,7 +327,7 @@ class Workers(Setting):
|
||||
default = 1
|
||||
desc = """\
|
||||
The number of worker process for handling requests.
|
||||
|
||||
|
||||
A positive integer generally in the 2-4 x $(NUM_CORES) range. You'll
|
||||
want to vary this a bit to find the best for your particular
|
||||
application's work load.
|
||||
@ -342,18 +342,18 @@ class WorkerClass(Setting):
|
||||
default = "sync"
|
||||
desc = """\
|
||||
The type of workers to use.
|
||||
|
||||
|
||||
The default class (sync) should handle most 'normal' types of workloads.
|
||||
You'll want to read http://gunicorn.org/design.html for information on
|
||||
when you might want to choose one of the other worker classes.
|
||||
|
||||
|
||||
A string referring to one of the following bundled classes:
|
||||
|
||||
|
||||
* ``sync``
|
||||
* ``eventlet`` - Requires eventlet >= 0.9.7
|
||||
* ``gevent`` - Requires gevent >= 0.12.2 (?)
|
||||
* ``tornado`` - Requires tornado >= 0.2
|
||||
|
||||
|
||||
Optionally, you can provide your own worker by giving gunicorn a
|
||||
python path to a subclass of gunicorn.workers.base.Worker. This
|
||||
alternative syntax will load the gevent class:
|
||||
@ -371,7 +371,7 @@ class WorkerConnections(Setting):
|
||||
default = 1000
|
||||
desc = """\
|
||||
The maximum number of simultaneous clients.
|
||||
|
||||
|
||||
This setting only affects the Eventlet and Gevent worker types.
|
||||
"""
|
||||
|
||||
@ -385,11 +385,11 @@ class MaxRequests(Setting):
|
||||
default = 0
|
||||
desc = """\
|
||||
The maximum number of requests a worker will process before restarting.
|
||||
|
||||
|
||||
Any value greater than zero will limit the number of requests a work
|
||||
will process before automatically restarting. This is a simple method
|
||||
to help limit the damage of memory leaks.
|
||||
|
||||
|
||||
If this is set to zero (the default) then the automatic worker
|
||||
restarts are disabled.
|
||||
"""
|
||||
@ -404,7 +404,7 @@ class Timeout(Setting):
|
||||
default = 30
|
||||
desc = """\
|
||||
Workers silent for more than this many seconds are killed and restarted.
|
||||
|
||||
|
||||
Generally set to thirty seconds. Only set this noticeably higher if
|
||||
you're sure of the repercussions for sync workers. For the non sync
|
||||
workers it just means that the worker process is still communicating and
|
||||
@ -421,8 +421,8 @@ class Keepalive(Setting):
|
||||
default = 2
|
||||
desc = """\
|
||||
The number of seconds to wait for requests on a Keep-Alive connection.
|
||||
|
||||
Generally set in the 1-5 seconds range.
|
||||
|
||||
Generally set in the 1-5 seconds range.
|
||||
"""
|
||||
|
||||
class Debug(Setting):
|
||||
@ -434,7 +434,7 @@ class Debug(Setting):
|
||||
default = False
|
||||
desc = """\
|
||||
Turn on debugging in the server.
|
||||
|
||||
|
||||
This limits the number of worker processes to 1 and changes some error
|
||||
handling that's sent to clients.
|
||||
"""
|
||||
@ -448,8 +448,8 @@ class Spew(Setting):
|
||||
default = False
|
||||
desc = """\
|
||||
Install a trace function that spews every line executed by the server.
|
||||
|
||||
This is the nuclear option.
|
||||
|
||||
This is the nuclear option.
|
||||
"""
|
||||
|
||||
class PreloadApp(Setting):
|
||||
@ -461,7 +461,7 @@ class PreloadApp(Setting):
|
||||
default = False
|
||||
desc = """\
|
||||
Load application code before the worker processes are forked.
|
||||
|
||||
|
||||
By preloading an application you can save some RAM resources as well as
|
||||
speed up server boot times. Although, if you defer application loading
|
||||
to each worker process, you can reload your application code easily by
|
||||
@ -477,7 +477,7 @@ class Daemon(Setting):
|
||||
default = False
|
||||
desc = """\
|
||||
Daemonize the Gunicorn process.
|
||||
|
||||
|
||||
Detaches the server from the controlling terminal and enters the
|
||||
background.
|
||||
"""
|
||||
@ -491,7 +491,7 @@ class Pidfile(Setting):
|
||||
default = None
|
||||
desc = """\
|
||||
A filename to use for the PID file.
|
||||
|
||||
|
||||
If not set, no PID file will be written.
|
||||
"""
|
||||
|
||||
@ -504,7 +504,7 @@ class User(Setting):
|
||||
default = os.geteuid()
|
||||
desc = """\
|
||||
Switch worker processes to run as this user.
|
||||
|
||||
|
||||
A valid user id (as an integer) or the name of a user that can be
|
||||
retrieved with a call to pwd.getpwnam(value) or None to not change
|
||||
the worker process user.
|
||||
@ -519,7 +519,7 @@ class Group(Setting):
|
||||
default = os.getegid()
|
||||
desc = """\
|
||||
Switch worker process to run as this group.
|
||||
|
||||
|
||||
A valid group id (as an integer) or the name of a user that can be
|
||||
retrieved with a call to pwd.getgrnam(value) or None to not change
|
||||
the worker processes group.
|
||||
@ -535,9 +535,9 @@ class Umask(Setting):
|
||||
default = 0
|
||||
desc = """\
|
||||
A bit mask for the file mode on files written by Gunicorn.
|
||||
|
||||
|
||||
Note that this affects unix socket permissions.
|
||||
|
||||
|
||||
A valid value for the os.umask(mode) call or a string compatible with
|
||||
int(value, 0) (0 means Python guesses the base, so values like "0",
|
||||
"0xFF", "0022" are valid for decimal, hex, and octal representations)
|
||||
@ -551,9 +551,9 @@ class TmpUploadDir(Setting):
|
||||
default = None
|
||||
desc = """\
|
||||
Directory to store temporary request data as they are read.
|
||||
|
||||
|
||||
This may disappear in the near future.
|
||||
|
||||
|
||||
This path should be writable by the process permissions set for Gunicorn
|
||||
workers. If not specified, Gunicorn will choose a system generated
|
||||
temporary directory.
|
||||
@ -599,10 +599,10 @@ class AccessLog(Setting):
|
||||
cli = ["--access-logfile"]
|
||||
meta = "FILE"
|
||||
validator = validate_string
|
||||
default = None
|
||||
default = None
|
||||
desc = """\
|
||||
The Access log file to write to.
|
||||
|
||||
|
||||
"-" means log to stdout.
|
||||
"""
|
||||
|
||||
@ -612,7 +612,7 @@ class AccessLogFormat(Setting):
|
||||
cli = ["--access-logformat"]
|
||||
meta = "STRING"
|
||||
validator = validate_string
|
||||
default = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
|
||||
default = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
|
||||
desc = """\
|
||||
The Access log format .
|
||||
|
||||
@ -631,7 +631,7 @@ class AccessLogFormat(Setting):
|
||||
T: request time in seconds
|
||||
D: request time in microseconds
|
||||
|
||||
You can also pass any WSGI request header as a parameter.
|
||||
You can also pass any WSGI request header as a parameter.
|
||||
(ex '%(HTTP_HOST)s').
|
||||
"""
|
||||
|
||||
@ -644,7 +644,7 @@ class ErrorLog(Setting):
|
||||
default = "-"
|
||||
desc = """\
|
||||
The Error log file to write to.
|
||||
|
||||
|
||||
"-" means log to stdout.
|
||||
"""
|
||||
|
||||
@ -657,9 +657,9 @@ class Loglevel(Setting):
|
||||
default = "info"
|
||||
desc = """\
|
||||
The granularity of Error log outputs.
|
||||
|
||||
|
||||
Valid level names are:
|
||||
|
||||
|
||||
* debug
|
||||
* info
|
||||
* warning
|
||||
@ -681,8 +681,8 @@ class LoggerClass(Setting):
|
||||
normal usages in logging. It provides error and access logging.
|
||||
|
||||
You can provide your own worker by giving gunicorn a
|
||||
python path to a subclass like gunicorn.glogging.Logger.
|
||||
Alternatively the syntax can also load the Logger class
|
||||
python path to a subclass like gunicorn.glogging.Logger.
|
||||
Alternatively the syntax can also load the Logger class
|
||||
with `egg:gunicorn#simple`
|
||||
"""
|
||||
|
||||
@ -695,12 +695,12 @@ class Procname(Setting):
|
||||
default = None
|
||||
desc = """\
|
||||
A base to use with setproctitle for process naming.
|
||||
|
||||
|
||||
This affects things like ``ps`` and ``top``. If you're going to be
|
||||
running more than one instance of Gunicorn you'll probably want to set a
|
||||
name to tell them apart. This requires that you install the setproctitle
|
||||
module.
|
||||
|
||||
|
||||
It defaults to 'gunicorn'.
|
||||
"""
|
||||
|
||||
@ -723,7 +723,7 @@ class OnStarting(Setting):
|
||||
default = staticmethod(on_starting)
|
||||
desc = """\
|
||||
Called just before the master process is initialized.
|
||||
|
||||
|
||||
The callable needs to accept a single instance variable for the Arbiter.
|
||||
"""
|
||||
|
||||
@ -752,7 +752,7 @@ class WhenReady(Setting):
|
||||
default = staticmethod(start_server)
|
||||
desc = """\
|
||||
Called just after the server is started.
|
||||
|
||||
|
||||
The callable needs to accept a single instance variable for the Arbiter.
|
||||
"""
|
||||
|
||||
@ -766,11 +766,11 @@ class Prefork(Setting):
|
||||
default = staticmethod(pre_fork)
|
||||
desc = """\
|
||||
Called just before a worker is forked.
|
||||
|
||||
|
||||
The callable needs to accept two instance variables for the Arbiter and
|
||||
new Worker.
|
||||
"""
|
||||
|
||||
|
||||
class Postfork(Setting):
|
||||
name = "post_fork"
|
||||
section = "Server Hooks"
|
||||
@ -781,7 +781,7 @@ class Postfork(Setting):
|
||||
default = staticmethod(post_fork)
|
||||
desc = """\
|
||||
Called just after a worker has been forked.
|
||||
|
||||
|
||||
The callable needs to accept two instance variables for the Arbiter and
|
||||
new Worker.
|
||||
"""
|
||||
@ -796,7 +796,7 @@ class PreExec(Setting):
|
||||
default = staticmethod(pre_exec)
|
||||
desc = """\
|
||||
Called just before a new master process is forked.
|
||||
|
||||
|
||||
The callable needs to accept a single instance variable for the Arbiter.
|
||||
"""
|
||||
|
||||
@ -810,7 +810,7 @@ class PreRequest(Setting):
|
||||
default = staticmethod(pre_request)
|
||||
desc = """\
|
||||
Called just before a worker processes the request.
|
||||
|
||||
|
||||
The callable needs to accept two instance variables for the Worker and
|
||||
the Request.
|
||||
"""
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
"""The debug module contains utilities and functions for better
|
||||
"""The debug module contains utilities and functions for better
|
||||
debugging Gunicorn."""
|
||||
|
||||
import sys
|
||||
@ -69,5 +69,5 @@ def unspew():
|
||||
"""Remove the trace hook installed by spew.
|
||||
"""
|
||||
sys.settrace(None)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ class HaltServer(Exception):
|
||||
def __init__(self, reason, exit_status=1):
|
||||
self.reason = reason
|
||||
self.exit_status = exit_status
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "<HaltServer %r %d>" % (self.reason, self.exit_status)
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import datetime
|
||||
@ -39,7 +39,7 @@ class Logger(object):
|
||||
|
||||
loglevel = self.LOG_LEVELS.get(cfg.loglevel.lower(), logging.INFO)
|
||||
self.error_log.setLevel(loglevel)
|
||||
|
||||
|
||||
# always info in access log
|
||||
self.access_log.setLevel(logging.INFO)
|
||||
|
||||
@ -100,13 +100,13 @@ class Logger(object):
|
||||
'D': str(request_time.microseconds)
|
||||
}
|
||||
|
||||
# add WSGI request headers
|
||||
# add WSGI request headers
|
||||
atoms.update(dict([(k,v) for k, v in environ.items() \
|
||||
if k.startswith('HTTP_')]))
|
||||
|
||||
for k, v in atoms.items():
|
||||
atoms[k] = v.replace('"', '\\"')
|
||||
|
||||
|
||||
try:
|
||||
self.access_log.info(self.cfg.access_log_format % atoms)
|
||||
except:
|
||||
@ -138,12 +138,12 @@ class Logger(object):
|
||||
util.close_on_exec(handler.stream.fileno())
|
||||
handler.release()
|
||||
|
||||
|
||||
|
||||
def _get_gunicorn_handler(self, log):
|
||||
for h in log.handlers:
|
||||
if getattr(h, "_gunicorn", False) == True:
|
||||
return h
|
||||
|
||||
|
||||
def _set_handler(self, log, output, fmt):
|
||||
# remove previous gunicorn log handler
|
||||
h = self._get_gunicorn_handler(log)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import errno
|
||||
@ -35,7 +35,7 @@ def sendfile(fdout, fdin, offset, nbytes):
|
||||
ctypes.c_int]
|
||||
_nbytes = ctypes.c_uint64(nbytes)
|
||||
result = _sendfile(fdin, fdout, offset, _nbytes, None, 0)
|
||||
|
||||
|
||||
if result == -1:
|
||||
e = ctypes.get_errno()
|
||||
if e == errno.EAGAIN and _nbytes.value is not None:
|
||||
@ -60,7 +60,7 @@ def sendfile(fdout, fdin, offset, nbytes):
|
||||
ctypes.POINTER(ctypes.c_uint64), ctypes.c_size_t]
|
||||
|
||||
_offset = ctypes.c_uint64(offset)
|
||||
sent = _sendfile(fdout, fdin, _offset, nbytes)
|
||||
sent = _sendfile(fdout, fdin, _offset, nbytes)
|
||||
if sent == -1:
|
||||
e = ctypes.get_errno()
|
||||
raise OSError(e, os.strerror(e))
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import sys
|
||||
@ -18,7 +18,7 @@ class ChunkedReader(object):
|
||||
self.req = req
|
||||
self.parser = self.parse_chunked(unreader)
|
||||
self.buf = StringIO()
|
||||
|
||||
|
||||
def read(self, size):
|
||||
if not isinstance(size, (int, long)):
|
||||
raise TypeError("size must be an integral type")
|
||||
@ -40,11 +40,11 @@ class ChunkedReader(object):
|
||||
self.buf.truncate(0)
|
||||
self.buf.write(rest)
|
||||
return ret
|
||||
|
||||
|
||||
def parse_trailers(self, unreader, data):
|
||||
buf = StringIO()
|
||||
buf.write(data)
|
||||
|
||||
|
||||
idx = buf.getvalue().find("\r\n\r\n")
|
||||
done = buf.getvalue()[:2] == "\r\n"
|
||||
while idx < 0 and not done:
|
||||
@ -73,7 +73,7 @@ class ChunkedReader(object):
|
||||
rest += unreader.read()
|
||||
if rest[:2] != '\r\n':
|
||||
raise ChunkMissingTerminator(rest[:2])
|
||||
(size, rest) = self.parse_chunk_size(unreader, data=rest[2:])
|
||||
(size, rest) = self.parse_chunk_size(unreader, data=rest[2:])
|
||||
|
||||
def parse_chunk_size(self, unreader, data=None):
|
||||
buf = StringIO()
|
||||
@ -87,7 +87,7 @@ class ChunkedReader(object):
|
||||
|
||||
data = buf.getvalue()
|
||||
line, rest_chunk = data[:idx], data[idx+2:]
|
||||
|
||||
|
||||
chunk_size = line.split(";", 1)[0].strip()
|
||||
try:
|
||||
chunk_size = int(chunk_size, 16)
|
||||
@ -112,18 +112,18 @@ class LengthReader(object):
|
||||
def __init__(self, unreader, length):
|
||||
self.unreader = unreader
|
||||
self.length = length
|
||||
|
||||
|
||||
def read(self, size):
|
||||
if not isinstance(size, (int, long)):
|
||||
raise TypeError("size must be an integral type")
|
||||
|
||||
|
||||
size = min(self.length, size)
|
||||
if size < 0:
|
||||
raise ValueError("Size must be positive.")
|
||||
if size == 0:
|
||||
return ""
|
||||
|
||||
|
||||
|
||||
|
||||
buf = StringIO()
|
||||
data = self.unreader.read()
|
||||
while data:
|
||||
@ -131,7 +131,7 @@ class LengthReader(object):
|
||||
if buf.tell() >= size:
|
||||
break
|
||||
data = self.unreader.read()
|
||||
|
||||
|
||||
buf = buf.getvalue()
|
||||
ret, rest = buf[:size], buf[size:]
|
||||
self.unreader.unread(rest)
|
||||
@ -143,7 +143,7 @@ class EOFReader(object):
|
||||
self.unreader = unreader
|
||||
self.buf = StringIO()
|
||||
self.finished = False
|
||||
|
||||
|
||||
def read(self, size):
|
||||
if not isinstance(size, (int, long)):
|
||||
raise TypeError("size must be an integral type")
|
||||
@ -151,7 +151,7 @@ class EOFReader(object):
|
||||
raise ValueError("Size must be positive.")
|
||||
if size == 0:
|
||||
return ""
|
||||
|
||||
|
||||
if self.finished:
|
||||
data = self.buf.getvalue()
|
||||
ret, rest = data[:size], data[size:]
|
||||
@ -179,10 +179,10 @@ class Body(object):
|
||||
def __init__(self, reader):
|
||||
self.reader = reader
|
||||
self.buf = StringIO()
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
|
||||
def next(self):
|
||||
ret = self.readline()
|
||||
if not ret:
|
||||
@ -197,7 +197,7 @@ class Body(object):
|
||||
elif size < 0:
|
||||
return sys.maxint
|
||||
return size
|
||||
|
||||
|
||||
def read(self, size=None):
|
||||
size = self.getsize(size)
|
||||
if size == 0:
|
||||
@ -221,12 +221,12 @@ class Body(object):
|
||||
self.buf.truncate(0)
|
||||
self.buf.write(rest)
|
||||
return ret
|
||||
|
||||
|
||||
def readline(self, size=None):
|
||||
size = self.getsize(size)
|
||||
if size == 0:
|
||||
return ""
|
||||
|
||||
|
||||
line = self.buf.getvalue()
|
||||
idx = line.find("\n")
|
||||
if idx >= 0:
|
||||
@ -234,7 +234,7 @@ class Body(object):
|
||||
self.buf.truncate(0)
|
||||
self.buf.write(line[idx+1:])
|
||||
return ret
|
||||
|
||||
|
||||
self.buf.truncate(0)
|
||||
ch = ""
|
||||
buf = [line]
|
||||
@ -246,7 +246,7 @@ class Body(object):
|
||||
lsize += 1
|
||||
buf.append(ch)
|
||||
return "".join(buf)
|
||||
|
||||
|
||||
def readlines(self, size=None):
|
||||
ret = []
|
||||
data = self.read()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
class ParseException(Exception):
|
||||
@ -26,18 +26,18 @@ class InvalidRequestMethod(ParseException):
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid HTTP method: %r" % self.method
|
||||
|
||||
|
||||
class InvalidHTTPVersion(ParseException):
|
||||
def __init__(self, version):
|
||||
self.version = version
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid HTTP Version: %s" % self.version
|
||||
|
||||
class InvalidHeader(ParseException):
|
||||
def __init__(self, hdr):
|
||||
self.hdr = hdr
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid HTTP Header: %r" % self.hdr
|
||||
|
||||
@ -51,13 +51,13 @@ class InvalidHeaderName(ParseException):
|
||||
class InvalidChunkSize(ParseException):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid chunk size: %r" % self.data
|
||||
|
||||
class ChunkMissingTerminator(ParseException):
|
||||
def __init__(self, term):
|
||||
self.term = term
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid chunk terminator is not '\\r\\n': %r" % self.term
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import re
|
||||
@ -28,7 +28,7 @@ class Message(object):
|
||||
unused = self.parse(self.unreader)
|
||||
self.unreader.unread(unused)
|
||||
self.set_body_reader()
|
||||
|
||||
|
||||
def parse(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@ -50,12 +50,12 @@ class Message(object):
|
||||
if self.hdrre.search(name):
|
||||
raise InvalidHeaderName(name)
|
||||
name, value = name.strip(), [value.lstrip()]
|
||||
|
||||
|
||||
# Consume value continuation lines
|
||||
while len(lines) and lines[0].startswith((" ", "\t")):
|
||||
value.append(lines.pop(0))
|
||||
value = ''.join(value).rstrip()
|
||||
|
||||
|
||||
headers.append((name, value))
|
||||
return headers
|
||||
|
||||
@ -99,7 +99,7 @@ class Request(Message):
|
||||
def __init__(self, unreader):
|
||||
self.methre = re.compile("[A-Z0-9$-_.]{3,20}")
|
||||
self.versre = re.compile("HTTP/(\d+).(\d+)")
|
||||
|
||||
|
||||
self.method = None
|
||||
self.uri = None
|
||||
self.scheme = None
|
||||
@ -119,12 +119,12 @@ class Request(Message):
|
||||
raise StopIteration()
|
||||
raise NoMoreData(buf.getvalue())
|
||||
buf.write(data)
|
||||
|
||||
|
||||
def parse(self, unreader):
|
||||
buf = StringIO()
|
||||
|
||||
self.get_data(unreader, buf, stop=True)
|
||||
|
||||
|
||||
# Request line
|
||||
idx = buf.getvalue().find("\r\n")
|
||||
while idx < 0:
|
||||
@ -134,8 +134,8 @@ class Request(Message):
|
||||
rest = buf.getvalue()[idx+2:] # Skip \r\n
|
||||
buf = StringIO()
|
||||
buf.write(rest)
|
||||
|
||||
|
||||
|
||||
|
||||
# Headers
|
||||
idx = buf.getvalue().find("\r\n\r\n")
|
||||
|
||||
@ -144,7 +144,7 @@ class Request(Message):
|
||||
self.get_data(unreader, buf)
|
||||
idx = buf.getvalue().find("\r\n\r\n")
|
||||
done = buf.getvalue()[:2] == "\r\n"
|
||||
|
||||
|
||||
if done:
|
||||
self.unreader.unread(buf.getvalue()[2:])
|
||||
return ""
|
||||
@ -154,7 +154,7 @@ class Request(Message):
|
||||
ret = buf.getvalue()[idx+4:]
|
||||
buf = StringIO()
|
||||
return ret
|
||||
|
||||
|
||||
def parse_request_line(self, line):
|
||||
bits = line.split(None, 2)
|
||||
if len(bits) != 3:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from gunicorn.http.message import Request
|
||||
@ -17,18 +17,18 @@ class Parser(object):
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
|
||||
def next(self):
|
||||
# Stop if HTTP dictates a stop.
|
||||
if self.mesg and self.mesg.should_close():
|
||||
raise StopIteration()
|
||||
|
||||
|
||||
# Discard any unread body of the previous message
|
||||
if self.mesg:
|
||||
data = self.mesg.body.read(8192)
|
||||
while data:
|
||||
data = self.mesg.body.read(8192)
|
||||
|
||||
|
||||
# Parse the next request
|
||||
self.mesg = self.mesg_class(self.unreader)
|
||||
if not self.mesg:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import os
|
||||
@ -16,10 +16,10 @@ except ImportError:
|
||||
class Unreader(object):
|
||||
def __init__(self):
|
||||
self.buf = StringIO()
|
||||
|
||||
|
||||
def chunk(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def read(self, size=None):
|
||||
if size is not None and not isinstance(size, (int, long)):
|
||||
raise TypeError("size parameter must be an int or long.")
|
||||
@ -48,7 +48,7 @@ class Unreader(object):
|
||||
self.buf.truncate(0)
|
||||
self.buf.write(data[size:])
|
||||
return data[:size]
|
||||
|
||||
|
||||
def unread(self, data):
|
||||
self.buf.seek(0, os.SEEK_END)
|
||||
self.buf.write(data)
|
||||
@ -58,7 +58,7 @@ class SocketUnreader(Unreader):
|
||||
super(SocketUnreader, self).__init__()
|
||||
self.sock = sock
|
||||
self.mxchunk = max_chunk
|
||||
|
||||
|
||||
def chunk(self):
|
||||
return self.sock.recv(self.mxchunk)
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import logging
|
||||
@ -59,7 +59,7 @@ def create(req, sock, client, server, cfg):
|
||||
"CONTENT_TYPE": "",
|
||||
"CONTENT_LENGTH": ""
|
||||
}
|
||||
|
||||
|
||||
# authors should be aware that REMOTE_HOST and REMOTE_ADDR
|
||||
# may not qualify the remote addr:
|
||||
# http://www.ietf.org/rfc/rfc3875
|
||||
@ -98,7 +98,7 @@ def create(req, sock, client, server, cfg):
|
||||
environ[key] = hdr_value
|
||||
|
||||
environ['wsgi.url_scheme'] = url_scheme
|
||||
|
||||
|
||||
if isinstance(forward, basestring):
|
||||
# we only took the last one
|
||||
# http://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
@ -121,7 +121,7 @@ def create(req, sock, client, server, cfg):
|
||||
|
||||
remote = (host, port)
|
||||
else:
|
||||
remote = forward
|
||||
remote = forward
|
||||
|
||||
environ['REMOTE_ADDR'] = remote[0]
|
||||
environ['REMOTE_PORT'] = str(remote[1])
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
#
|
||||
# Copyright 2001-2005 by Vinay Sajip. All Rights Reserved.
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from optparse import make_option
|
||||
import sys
|
||||
|
||||
|
||||
|
||||
import django
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.conf import settings
|
||||
@ -56,17 +56,17 @@ class Command(BaseCommand):
|
||||
option_list = BaseCommand.option_list + GUNICORN_OPTIONS
|
||||
help = "Starts a fully-functional Web server using gunicorn."
|
||||
args = '[optional port number, or ipaddr:port or unix:/path/to/sockfile]'
|
||||
|
||||
|
||||
# Validation is called explicitly each time the server is reloaded.
|
||||
requires_model_validation = False
|
||||
|
||||
|
||||
def handle(self, addrport=None, *args, **options):
|
||||
if args:
|
||||
raise CommandError('Usage is run_gunicorn %s' % self.args)
|
||||
|
||||
|
||||
if addrport:
|
||||
options['bind'] = addrport
|
||||
|
||||
|
||||
options['default_proc_name'] = settings.SETTINGS_MODULE
|
||||
|
||||
admin_media_path = options.pop('admin_media_path', '')
|
||||
@ -74,11 +74,11 @@ class Command(BaseCommand):
|
||||
|
||||
print "Validating models..."
|
||||
self.validate(display_num_errors=True)
|
||||
print "\nDjango version %s, using settings %r" % (django.get_version(),
|
||||
print "\nDjango version %s, using settings %r" % (django.get_version(),
|
||||
settings.SETTINGS_MODULE)
|
||||
print "Server is running"
|
||||
print "Quit the server with %s." % quit_command
|
||||
|
||||
|
||||
# django.core.management.base forces the locale to en-us.
|
||||
translation.activate(settings.LANGUAGE_CODE)
|
||||
DjangoApplicationCommand(options, admin_media_path).run()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from __future__ import with_statement
|
||||
@ -20,7 +20,7 @@ class Pidfile(object):
|
||||
def __init__(self, fname):
|
||||
self.fname = fname
|
||||
self.pid = None
|
||||
|
||||
|
||||
def create(self, pid):
|
||||
oldpid = self.validate()
|
||||
if oldpid:
|
||||
@ -30,7 +30,7 @@ class Pidfile(object):
|
||||
"(or pid file '%s' is stale)" % (os.getpid(), self.fname))
|
||||
|
||||
self.pid = pid
|
||||
|
||||
|
||||
# Write pidfile
|
||||
fdir = os.path.dirname(self.fname)
|
||||
if fdir and not os.path.isdir(fdir):
|
||||
@ -43,14 +43,14 @@ class Pidfile(object):
|
||||
self.fname = fname
|
||||
os.close(fd)
|
||||
|
||||
# set permissions to -rw-r--r--
|
||||
# set permissions to -rw-r--r--
|
||||
os.chmod(self.fname, 420)
|
||||
|
||||
|
||||
def rename(self, path):
|
||||
self.unlink()
|
||||
self.fname = path
|
||||
self.create(self.pid)
|
||||
|
||||
|
||||
def unlink(self):
|
||||
""" delete pidfile"""
|
||||
try:
|
||||
@ -61,7 +61,7 @@ class Pidfile(object):
|
||||
os.unlink(self.fname)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def validate(self):
|
||||
""" Validate pidfile and make it stale if needed"""
|
||||
if not self.fname:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import errno
|
||||
@ -14,7 +14,7 @@ from gunicorn import util
|
||||
|
||||
|
||||
class BaseSocket(object):
|
||||
|
||||
|
||||
def __init__(self, conf, log, fd=None):
|
||||
self.log = log
|
||||
self.conf = conf
|
||||
@ -24,13 +24,13 @@ class BaseSocket(object):
|
||||
else:
|
||||
sock = socket.fromfd(fd, self.FAMILY, socket.SOCK_STREAM)
|
||||
self.sock = self.set_options(sock, bound=(fd is not None))
|
||||
|
||||
|
||||
def __str__(self, name):
|
||||
return "<socket %d>" % self.sock.fileno()
|
||||
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.sock, name)
|
||||
|
||||
|
||||
def set_options(self, sock, bound=False):
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
if not bound:
|
||||
@ -38,10 +38,10 @@ class BaseSocket(object):
|
||||
sock.setblocking(0)
|
||||
sock.listen(self.conf.backlog)
|
||||
return sock
|
||||
|
||||
|
||||
def bind(self, sock):
|
||||
sock.bind(self.address)
|
||||
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
self.sock.close()
|
||||
@ -51,12 +51,12 @@ class BaseSocket(object):
|
||||
del self.sock
|
||||
|
||||
class TCPSocket(BaseSocket):
|
||||
|
||||
|
||||
FAMILY = socket.AF_INET
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "http://%s:%d" % self.sock.getsockname()
|
||||
|
||||
|
||||
def set_options(self, sock, bound=False):
|
||||
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
return super(TCPSocket, self).set_options(sock, bound=bound)
|
||||
@ -70,9 +70,9 @@ class TCP6Socket(TCPSocket):
|
||||
return "http://[%s]:%d" % (host, port)
|
||||
|
||||
class UnixSocket(BaseSocket):
|
||||
|
||||
|
||||
FAMILY = socket.AF_UNIX
|
||||
|
||||
|
||||
def __init__(self, conf, log, fd=None):
|
||||
if fd is None:
|
||||
try:
|
||||
@ -80,16 +80,16 @@ class UnixSocket(BaseSocket):
|
||||
except OSError:
|
||||
pass
|
||||
super(UnixSocket, self).__init__(conf, log, fd=fd)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "unix:%s" % self.address
|
||||
|
||||
|
||||
def bind(self, sock):
|
||||
old_umask = os.umask(self.conf.umask)
|
||||
sock.bind(self.address)
|
||||
util.chown(self.address, self.conf.uid, self.conf.gid)
|
||||
os.umask(old_umask)
|
||||
|
||||
|
||||
def close(self):
|
||||
super(UnixSocket, self).close()
|
||||
os.unlink(self.address)
|
||||
@ -103,7 +103,7 @@ def create_socket(conf, log):
|
||||
"""
|
||||
# get it only once
|
||||
addr = conf.address
|
||||
|
||||
|
||||
if isinstance(addr, tuple):
|
||||
if util.is_ipv6(addr[0]):
|
||||
sock_type = TCP6Socket
|
||||
@ -127,7 +127,7 @@ def create_socket(conf, log):
|
||||
# If we fail to create a socket from GUNICORN_FD
|
||||
# we fall through and try and open the socket
|
||||
# normally.
|
||||
|
||||
|
||||
for i in range(5):
|
||||
try:
|
||||
return sock_type(conf, log)
|
||||
@ -140,6 +140,6 @@ def create_socket(conf, log):
|
||||
if i < 5:
|
||||
log.error("Retrying in 1 second.")
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
log.error("Can't connect to %s", str(addr))
|
||||
sys.exit(1)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
|
||||
@ -55,11 +55,11 @@ hop_headers = set("""
|
||||
te trailers transfer-encoding upgrade
|
||||
server date
|
||||
""".split())
|
||||
|
||||
|
||||
try:
|
||||
from setproctitle import setproctitle
|
||||
def _setproctitle(title):
|
||||
setproctitle("gunicorn: %s" % title)
|
||||
setproctitle("gunicorn: %s" % title)
|
||||
except ImportError:
|
||||
def _setproctitle(title):
|
||||
return
|
||||
@ -82,9 +82,9 @@ def load_class(uri, default="sync", section="gunicorn.workers"):
|
||||
if uri.startswith("#"):
|
||||
uri = uri[1:]
|
||||
|
||||
return pkg_resources.load_entry_point("gunicorn",
|
||||
return pkg_resources.load_entry_point("gunicorn",
|
||||
section, uri)
|
||||
except ImportError:
|
||||
except ImportError:
|
||||
raise RuntimeError("class uri invalid or not found")
|
||||
klass = components.pop(-1)
|
||||
mod = __import__('.'.join(components))
|
||||
@ -103,10 +103,10 @@ def set_owner_process(uid,gid):
|
||||
# versions of python < 2.6.2 don't manage unsigned int for
|
||||
# groups like on osx or fedora
|
||||
os.setgid(-ctypes.c_int(-gid).value)
|
||||
|
||||
|
||||
if uid:
|
||||
os.setuid(uid)
|
||||
|
||||
|
||||
def chown(path, uid, gid):
|
||||
try:
|
||||
os.chown(path, uid, gid)
|
||||
@ -122,7 +122,7 @@ def is_ipv6(addr):
|
||||
except socket.error: # not a valid address
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def parse_address(netloc, default_port=8000):
|
||||
if netloc.startswith("unix:"):
|
||||
return netloc.split("unix:")[1]
|
||||
@ -136,7 +136,7 @@ def parse_address(netloc, default_port=8000):
|
||||
host = "0.0.0.0"
|
||||
else:
|
||||
host = netloc.lower()
|
||||
|
||||
|
||||
#get port
|
||||
netloc = netloc.split(']')[-1]
|
||||
if ":" in netloc:
|
||||
@ -145,9 +145,9 @@ def parse_address(netloc, default_port=8000):
|
||||
raise RuntimeError("%r is not a valid port number." % port)
|
||||
port = int(port)
|
||||
else:
|
||||
port = default_port
|
||||
port = default_port
|
||||
return (host, port)
|
||||
|
||||
|
||||
def get_maxfd():
|
||||
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
||||
if (maxfd == resource.RLIM_INFINITY):
|
||||
@ -158,7 +158,7 @@ def close_on_exec(fd):
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||
flags |= fcntl.FD_CLOEXEC
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, flags)
|
||||
|
||||
|
||||
def set_non_blocking(fd):
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK
|
||||
fcntl.fcntl(fd, fcntl.F_SETFL, flags)
|
||||
@ -183,7 +183,7 @@ except ImportError:
|
||||
def write_chunk(sock, data):
|
||||
chunk = "".join(("%X\r\n" % len(data), data, "\r\n"))
|
||||
sock.sendall(chunk)
|
||||
|
||||
|
||||
def write(sock, data, chunked=False):
|
||||
if chunked:
|
||||
return write_chunk(sock, data)
|
||||
@ -199,7 +199,7 @@ def write_nonblock(sock, data, chunked=False):
|
||||
sock.setblocking(1)
|
||||
else:
|
||||
return write(sock, data, chunked)
|
||||
|
||||
|
||||
def writelines(sock, lines, chunked=False):
|
||||
for line in list(lines):
|
||||
write(sock, line, chunked)
|
||||
@ -229,7 +229,7 @@ def write_error(sock, status_int, reason, mesg):
|
||||
|
||||
def normalize_name(name):
|
||||
return "-".join([w.lower().capitalize() for w in name.split("-")])
|
||||
|
||||
|
||||
def import_app(module):
|
||||
parts = module.split(":", 1)
|
||||
if len(parts) == 1:
|
||||
@ -264,7 +264,7 @@ def http_date(timestamp=None):
|
||||
day, monthname[month], year,
|
||||
hh, mm, ss)
|
||||
return s
|
||||
|
||||
|
||||
def to_bytestring(s):
|
||||
""" convert to bytestring an unicode """
|
||||
if not isinstance(s, basestring):
|
||||
@ -289,11 +289,11 @@ def daemonize():
|
||||
|
||||
if os.fork():
|
||||
os._exit(0)
|
||||
|
||||
|
||||
os.umask(0)
|
||||
maxfd = get_maxfd()
|
||||
closerange(0, maxfd)
|
||||
|
||||
|
||||
os.open(REDIRECT_TO, os.O_RDWR)
|
||||
os.dup2(0, 1)
|
||||
os.dup2(0, 2)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from __future__ import with_statement
|
||||
@ -21,7 +21,7 @@ class AsyncWorker(base.Worker):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AsyncWorker, self).__init__(*args, **kwargs)
|
||||
self.worker_connections = self.cfg.worker_connections
|
||||
|
||||
|
||||
def timeout_ctx(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ class Worker(object):
|
||||
lambda x: getattr(signal, "SIG%s" % x),
|
||||
"HUP QUIT INT TERM USR1 USR2 WINCH CHLD".split()
|
||||
)
|
||||
|
||||
|
||||
PIPE = []
|
||||
|
||||
def __init__(self, age, ppid, socket, app, timeout, cfg, log):
|
||||
@ -47,11 +47,11 @@ class Worker(object):
|
||||
self.log = log
|
||||
self.debug = cfg.debug
|
||||
self.address = self.socket.getsockname()
|
||||
self.tmp = WorkerTmp(cfg)
|
||||
|
||||
self.tmp = WorkerTmp(cfg)
|
||||
|
||||
def __str__(self):
|
||||
return "<Worker %s>" % self.pid
|
||||
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
return os.getpid()
|
||||
@ -88,7 +88,7 @@ class Worker(object):
|
||||
self.PIPE = os.pipe()
|
||||
map(util.set_non_blocking, self.PIPE)
|
||||
map(util.close_on_exec, self.PIPE)
|
||||
|
||||
|
||||
# Prevent fd inherientence
|
||||
util.close_on_exec(self.socket)
|
||||
util.close_on_exec(self.tmp.fileno())
|
||||
@ -96,9 +96,9 @@ class Worker(object):
|
||||
self.log.close_on_exec()
|
||||
|
||||
self.init_signals()
|
||||
|
||||
|
||||
self.wsgi = self.app.wsgi()
|
||||
|
||||
|
||||
# Enter main run loop
|
||||
self.booted = True
|
||||
self.run()
|
||||
@ -118,7 +118,7 @@ class Worker(object):
|
||||
|
||||
def handle_usr1(self, sig, frame):
|
||||
self.log.reopen_files()
|
||||
|
||||
|
||||
def handle_quit(self, sig, frame):
|
||||
self.alive = False
|
||||
|
||||
@ -135,10 +135,10 @@ class Worker(object):
|
||||
|
||||
if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,
|
||||
InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,)):
|
||||
|
||||
|
||||
status_int = 400
|
||||
reason = "Bad Request"
|
||||
|
||||
|
||||
if isinstance(exc, InvalidRequestLine):
|
||||
mesg = "<p>Invalid Request Line '%s'</p>" % str(exc)
|
||||
elif isinstance(exc, InvalidRequestMethod):
|
||||
@ -147,7 +147,7 @@ class Worker(object):
|
||||
mesg = "<p>Invalid HTTP Version '%s'</p>" % str(exc)
|
||||
elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):
|
||||
mesg = "<p>Invalid Header '%s'</p>" % str(exc)
|
||||
|
||||
|
||||
if self.debug:
|
||||
tb = traceback.format_exc()
|
||||
mesg += "<h2>Traceback:</h2>\n<pre>%s</pre>" % tb
|
||||
@ -156,7 +156,7 @@ class Worker(object):
|
||||
util.write_error(client, status_int, reason, mesg)
|
||||
except:
|
||||
self.log.warning("Failed to send error message.")
|
||||
|
||||
|
||||
def handle_winch(self, sig, fname):
|
||||
# Ignore SIGWINCH in worker. Fixes a crash on OpenBSD.
|
||||
return
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from __future__ import with_statement
|
||||
@ -28,9 +28,9 @@ class EventletWorker(AsyncWorker):
|
||||
def init_process(self):
|
||||
hubs.use_hub()
|
||||
super(EventletWorker, self).init_process()
|
||||
|
||||
|
||||
def timeout_ctx(self):
|
||||
return eventlet.Timeout(self.cfg.keepalive, False)
|
||||
return eventlet.Timeout(self.cfg.keepalive, False)
|
||||
|
||||
def run(self):
|
||||
self.socket = GreenSocket(family_or_realsock=self.socket.sock)
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from gunicorn.workers.ggevent import BASE_WSGI_ENV, GeventWorker
|
||||
from gunicorn.workers.ggevent import BASE_WSGI_ENV, GeventWorker
|
||||
from gevent import wsgi
|
||||
|
||||
|
||||
@ -30,9 +30,9 @@ class WSGIHandler(wsgi.WSGIHandler):
|
||||
self.time_start = datetime.now()
|
||||
super(WSGIHandler, self).handle()
|
||||
|
||||
|
||||
|
||||
class WSGIServer(wsgi.WSGIServer):
|
||||
base_env = BASE_WSGI_ENV
|
||||
base_env = BASE_WSGI_ENV
|
||||
|
||||
class GeventWSGIWorker(GeventWorker):
|
||||
"The Gevent StreamServer based workers."
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import os
|
||||
@ -19,7 +19,7 @@ from gunicorn.workers.base import Worker
|
||||
from gunicorn import __version__ as gversion
|
||||
|
||||
class TornadoWorker(Worker):
|
||||
|
||||
|
||||
@classmethod
|
||||
def setup(cls):
|
||||
web = sys.modules.pop("tornado.web")
|
||||
@ -29,18 +29,18 @@ class TornadoWorker(Worker):
|
||||
self._headers["Server"] += " (Gunicorn/%s)" % gversion
|
||||
web.RequestHandler.clear = clear
|
||||
sys.modules["tornado.web"] = web
|
||||
|
||||
|
||||
def handle_quit(self, sig, frame):
|
||||
super(TornadoWorker, self).handle_quit(sig, frame)
|
||||
self.ioloop.stop()
|
||||
|
||||
def watchdog(self):
|
||||
self.notify()
|
||||
|
||||
|
||||
if self.ppid != os.getppid():
|
||||
self.log.info("Parent changed, shutting down: %s", self)
|
||||
self.ioloop.stop()
|
||||
|
||||
|
||||
def run(self):
|
||||
self.socket.setblocking(0)
|
||||
self.ioloop = IOLoop.instance()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
#
|
||||
|
||||
@ -16,7 +16,7 @@ import gunicorn.util as util
|
||||
import gunicorn.workers.base as base
|
||||
|
||||
class SyncWorker(base.Worker):
|
||||
|
||||
|
||||
def run(self):
|
||||
# self.socket appears to lose its blocking status after
|
||||
# we fork in the arbiter. Reset it here.
|
||||
@ -24,7 +24,7 @@ class SyncWorker(base.Worker):
|
||||
|
||||
while self.alive:
|
||||
self.notify()
|
||||
|
||||
|
||||
# Accept a connection. If we get an error telling us
|
||||
# that no connection is waiting we fall down to the
|
||||
# select which is where we'll wait for a bit for new
|
||||
@ -48,7 +48,7 @@ class SyncWorker(base.Worker):
|
||||
if self.ppid != os.getppid():
|
||||
self.log.info("Parent changed, shutting down: %s", self)
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
self.notify()
|
||||
ret = select.select([self.socket], [], self.PIPE, self.timeout)
|
||||
@ -63,7 +63,7 @@ class SyncWorker(base.Worker):
|
||||
else:
|
||||
return
|
||||
raise
|
||||
|
||||
|
||||
def handle(self, client, addr):
|
||||
try:
|
||||
parser = http.RequestParser(client)
|
||||
@ -78,7 +78,7 @@ class SyncWorker(base.Worker):
|
||||
self.log.debug("Ignoring EPIPE")
|
||||
except Exception, e:
|
||||
self.handle_error(client, e)
|
||||
finally:
|
||||
finally:
|
||||
util.close(client)
|
||||
|
||||
def handle_request(self, req, client, addr):
|
||||
@ -113,7 +113,7 @@ class SyncWorker(base.Worker):
|
||||
raise
|
||||
except Exception, e:
|
||||
# Only send back traceback in HTTP in debug mode.
|
||||
self.handle_error(client, e)
|
||||
self.handle_error(client, e)
|
||||
return
|
||||
finally:
|
||||
try:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -
|
||||
#
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# This file is part of gunicorn released under the MIT license.
|
||||
# See the NOTICE for more information.
|
||||
|
||||
import os
|
||||
@ -13,7 +13,7 @@ class WorkerTmp(object):
|
||||
def __init__(self, cfg):
|
||||
old_umask = os.umask(cfg.umask)
|
||||
fd, name = tempfile.mkstemp(prefix="wgunicorn-")
|
||||
|
||||
|
||||
# allows the process to write to the file
|
||||
util.chown(name, cfg.uid, cfg.gid)
|
||||
os.umask(old_umask)
|
||||
@ -28,7 +28,7 @@ class WorkerTmp(object):
|
||||
|
||||
self.spinner = 0
|
||||
|
||||
def notify(self):
|
||||
def notify(self):
|
||||
try:
|
||||
self.spinner = (self.spinner+1) % 2
|
||||
os.fchmod(self._tmp.fileno(), self.spinner)
|
||||
@ -42,6 +42,6 @@ class WorkerTmp(object):
|
||||
|
||||
def fileno(self):
|
||||
return self._tmp.fileno()
|
||||
|
||||
|
||||
def close(self):
|
||||
return self._tmp.close()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user