# -*- coding: utf-8 - # # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. try: import ctypes except MemoryError: # selinux execmem denial # https://bugzilla.redhat.com/show_bug.cgi?id=488396 ctypes = None except ImportError: # Python on Solaris compiled with Sun Studio doesn't have ctypes ctypes = None import fcntl import os import pkg_resources import random import resource import socket import sys import textwrap import time import inspect MAXFD = 1024 if (hasattr(os, "devnull")): REDIRECT_TO = os.devnull else: REDIRECT_TO = "/dev/null" timeout_default = object() CHUNK_SIZE = (16 * 1024) MAX_BODY = 1024 * 132 weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] monthname = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] # Server and Date aren't technically hop-by-hop # headers, but they are in the purview of the # origin server which the WSGI spec says we should # act like. So we drop them and add our own. # # In the future, concatenation server header values # might be better, but nothing else does it and # dropping them is easier. hop_headers = set(""" connection keep-alive proxy-authenticate proxy-authorization te trailers transfer-encoding upgrade server date """.split()) try: from setproctitle import setproctitle def _setproctitle(title): setproctitle("gunicorn: %s" % title) except ImportError: def _setproctitle(title): return try: from importlib import import_module except ImportError: def _resolve_name(name, package, level): """Return the absolute name of the module to be imported.""" if not hasattr(package, 'rindex'): raise ValueError("'package' not set to a string") dot = len(package) for x in xrange(level, 1, -1): try: dot = package.rindex('.', 0, dot) except ValueError: raise ValueError("attempted relative import beyond top-level " "package") return "%s.%s" % (package[:dot], name) def import_module(name, package=None): """Import a module. The 'package' argument is required when performing a relative import. It specifies the package to use as the anchor point from which to resolve the relative import to an absolute import. """ if name.startswith('.'): if not package: raise TypeError("relative imports require the 'package' argument") level = 0 for character in name: if character != '.': break level += 1 name = _resolve_name(name[level:], package, level) __import__(name) return sys.modules[name] def load_class(uri, default="sync", section="gunicorn.workers"): if inspect.isclass(uri): return uri if uri.startswith("egg:"): # uses entry points entry_str = uri.split("egg:")[1] try: dist, name = entry_str.rsplit("#",1) except ValueError: dist = entry_str name = default return pkg_resources.load_entry_point(dist, section, name) else: components = uri.split('.') if len(components) == 1: try: if uri.startswith("#"): uri = uri[1:] return pkg_resources.load_entry_point("gunicorn", section, uri) except ImportError, e: raise RuntimeError("class uri invalid or not found: " + "[%s]" % str(e)) klass = components.pop(-1) mod = __import__('.'.join(components)) for comp in components[1:]: mod = getattr(mod, comp) return getattr(mod, klass) def set_owner_process(uid,gid): """ set user and group of workers processes """ if gid: try: os.setgid(gid) except OverflowError: if not ctypes: raise # 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) except OverflowError: if not ctypes: raise os.chown(path, uid, -ctypes.c_int(-gid).value) def is_ipv6(addr): try: socket.inet_pton(socket.AF_INET6, 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] # get host if '[' in netloc and ']' in netloc: host = netloc.split(']')[0][1:].lower() elif ':' in netloc: host = netloc.split(':')[0].lower() elif netloc == "": host = "0.0.0.0" else: host = netloc.lower() #get port netloc = netloc.split(']')[-1] if ":" in netloc: port = netloc.split(':', 1)[1] if not port.isdigit(): raise RuntimeError("%r is not a valid port number." % port) port = int(port) else: port = default_port return (host, port) def get_maxfd(): maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] if (maxfd == resource.RLIM_INFINITY): maxfd = MAXFD return maxfd 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) def close(sock): try: sock.close() except socket.error: pass try: from os import closerange except ImportError: def closerange(fd_low, fd_high): # Iterate through and close all file descriptors. for fd in xrange(fd_low, fd_high): try: os.close(fd) except OSError: # ERROR, fd wasn't open to begin with (ignored) pass 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) sock.sendall(data) def write_nonblock(sock, data, chunked=False): timeout = sock.gettimeout() if timeout != 0.0: try: sock.setblocking(0) return write(sock, data, chunked) finally: sock.setblocking(1) else: return write(sock, data, chunked) def writelines(sock, lines, chunked=False): for line in list(lines): write(sock, line, chunked) def write_error(sock, status_int, reason, mesg): html = textwrap.dedent("""\