We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Workers restart with --max-requests=0 when --max-requests-jitter is set to nonzero value
To reproduce, start gunicorn like this:
```
gunicorn -w 1 --max-requests=0 --max-requests-jitter=10 -b 0.0.0.0:8000 api:app
```

Then direct some traffic to it and observe the following log output:
```
[2019-02-05 20:27:23 +0000] [19] [INFO] Starting gunicorn 19.9.0
[2019-02-05 20:27:23 +0000] [19] [INFO] Listening at: http://0.0.0.0:8000 (19)
[2019-02-05 20:27:23 +0000] [19] [INFO] Using worker: sync
[2019-02-05 20:27:23 +0000] [22] [INFO] Booting worker with pid: 22
[2019-02-05 20:27:37 +0000] [22] [INFO] Autorestarting worker after current request.
[2019-02-05 20:27:37 +0000] [22] [INFO] Worker exiting (pid: 22)
[2019-02-05 20:27:37 +0000] [24] [INFO] Booting worker with pid: 24
```

I expect that `--max-requests-jitter` has no effect when `--max-requests` is set to 0.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gunicorn/workers/base.py`
Content:
```
1 # -*- coding: utf-8 -
2 #
3 # This file is part of gunicorn released under the MIT license.
4 # See the NOTICE for more information.
5 
6 import io
7 import os
8 import signal
9 import sys
10 import time
11 import traceback
12 from datetime import datetime
13 from random import randint
14 from ssl import SSLError
15 
16 from gunicorn import util
17 from gunicorn.http.errors import (
18     ForbiddenProxyRequest, InvalidHeader,
19     InvalidHeaderName, InvalidHTTPVersion,
20     InvalidProxyLine, InvalidRequestLine,
21     InvalidRequestMethod, InvalidSchemeHeaders,
22     LimitRequestHeaders, LimitRequestLine,
23 )
24 from gunicorn.http.wsgi import Response, default_environ
25 from gunicorn.reloader import reloader_engines
26 from gunicorn.workers.workertmp import WorkerTmp
27 
28 
29 class Worker(object):
30 
31     SIGNALS = [getattr(signal, "SIG%s" % x)
32             for x in "ABRT HUP QUIT INT TERM USR1 USR2 WINCH CHLD".split()]
33 
34     PIPE = []
35 
36     def __init__(self, age, ppid, sockets, app, timeout, cfg, log):
37         """\
38         This is called pre-fork so it shouldn't do anything to the
39         current process. If there's a need to make process wide
40         changes you'll want to do that in ``self.init_process()``.
41         """
42         self.age = age
43         self.pid = "[booting]"
44         self.ppid = ppid
45         self.sockets = sockets
46         self.app = app
47         self.timeout = timeout
48         self.cfg = cfg
49         self.booted = False
50         self.aborted = False
51         self.reloader = None
52 
53         self.nr = 0
54         jitter = randint(0, cfg.max_requests_jitter)
55         self.max_requests = cfg.max_requests + jitter or sys.maxsize
56         self.alive = True
57         self.log = log
58         self.tmp = WorkerTmp(cfg)
59 
60     def __str__(self):
61         return "<Worker %s>" % self.pid
62 
63     def notify(self):
64         """\
65         Your worker subclass must arrange to have this method called
66         once every ``self.timeout`` seconds. If you fail in accomplishing
67         this task, the master process will murder your workers.
68         """
69         self.tmp.notify()
70 
71     def run(self):
72         """\
73         This is the mainloop of a worker process. You should override
74         this method in a subclass to provide the intended behaviour
75         for your particular evil schemes.
76         """
77         raise NotImplementedError()
78 
79     def init_process(self):
80         """\
81         If you override this method in a subclass, the last statement
82         in the function should be to call this method with
83         super(MyWorkerClass, self).init_process() so that the ``run()``
84         loop is initiated.
85         """
86 
87         # set environment' variables
88         if self.cfg.env:
89             for k, v in self.cfg.env.items():
90                 os.environ[k] = v
91 
92         util.set_owner_process(self.cfg.uid, self.cfg.gid,
93                                initgroups=self.cfg.initgroups)
94 
95         # Reseed the random number generator
96         util.seed()
97 
98         # For waking ourselves up
99         self.PIPE = os.pipe()
100         for p in self.PIPE:
101             util.set_non_blocking(p)
102             util.close_on_exec(p)
103 
104         # Prevent fd inheritance
105         for s in self.sockets:
106             util.close_on_exec(s)
107         util.close_on_exec(self.tmp.fileno())
108 
109         self.wait_fds = self.sockets + [self.PIPE[0]]
110 
111         self.log.close_on_exec()
112 
113         self.init_signals()
114 
115         # start the reloader
116         if self.cfg.reload:
117             def changed(fname):
118                 self.log.info("Worker reloading: %s modified", fname)
119                 self.alive = False
120                 self.cfg.worker_int(self)
121                 time.sleep(0.1)
122                 sys.exit(0)
123 
124             reloader_cls = reloader_engines[self.cfg.reload_engine]
125             self.reloader = reloader_cls(extra_files=self.cfg.reload_extra_files,
126                                          callback=changed)
127             self.reloader.start()
128 
129         self.load_wsgi()
130         self.cfg.post_worker_init(self)
131 
132         # Enter main run loop
133         self.booted = True
134         self.run()
135 
136     def load_wsgi(self):
137         try:
138             self.wsgi = self.app.wsgi()
139         except SyntaxError as e:
140             if not self.cfg.reload:
141                 raise
142 
143             self.log.exception(e)
144 
145             # fix from PR #1228
146             # storing the traceback into exc_tb will create a circular reference.
147             # per https://docs.python.org/2/library/sys.html#sys.exc_info warning,
148             # delete the traceback after use.
149             try:
150                 _, exc_val, exc_tb = sys.exc_info()
151                 self.reloader.add_extra_file(exc_val.filename)
152 
153                 tb_string = io.StringIO()
154                 traceback.print_tb(exc_tb, file=tb_string)
155                 self.wsgi = util.make_fail_app(tb_string.getvalue())
156             finally:
157                 del exc_tb
158 
159     def init_signals(self):
160         # reset signaling
161         for s in self.SIGNALS:
162             signal.signal(s, signal.SIG_DFL)
163         # init new signaling
164         signal.signal(signal.SIGQUIT, self.handle_quit)
165         signal.signal(signal.SIGTERM, self.handle_exit)
166         signal.signal(signal.SIGINT, self.handle_quit)
167         signal.signal(signal.SIGWINCH, self.handle_winch)
168         signal.signal(signal.SIGUSR1, self.handle_usr1)
169         signal.signal(signal.SIGABRT, self.handle_abort)
170 
171         # Don't let SIGTERM and SIGUSR1 disturb active requests
172         # by interrupting system calls
173         signal.siginterrupt(signal.SIGTERM, False)
174         signal.siginterrupt(signal.SIGUSR1, False)
175 
176         if hasattr(signal, 'set_wakeup_fd'):
177             signal.set_wakeup_fd(self.PIPE[1])
178 
179     def handle_usr1(self, sig, frame):
180         self.log.reopen_files()
181 
182     def handle_exit(self, sig, frame):
183         self.alive = False
184 
185     def handle_quit(self, sig, frame):
186         self.alive = False
187         # worker_int callback
188         self.cfg.worker_int(self)
189         time.sleep(0.1)
190         sys.exit(0)
191 
192     def handle_abort(self, sig, frame):
193         self.alive = False
194         self.cfg.worker_abort(self)
195         sys.exit(1)
196 
197     def handle_error(self, req, client, addr, exc):
198         request_start = datetime.now()
199         addr = addr or ('', -1)  # unix socket case
200         if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,
201                 InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,
202                 LimitRequestLine, LimitRequestHeaders,
203                 InvalidProxyLine, ForbiddenProxyRequest,
204                 InvalidSchemeHeaders,
205                 SSLError)):
206 
207             status_int = 400
208             reason = "Bad Request"
209 
210             if isinstance(exc, InvalidRequestLine):
211                 mesg = "Invalid Request Line '%s'" % str(exc)
212             elif isinstance(exc, InvalidRequestMethod):
213                 mesg = "Invalid Method '%s'" % str(exc)
214             elif isinstance(exc, InvalidHTTPVersion):
215                 mesg = "Invalid HTTP Version '%s'" % str(exc)
216             elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):
217                 mesg = "%s" % str(exc)
218                 if not req and hasattr(exc, "req"):
219                     req = exc.req  # for access log
220             elif isinstance(exc, LimitRequestLine):
221                 mesg = "%s" % str(exc)
222             elif isinstance(exc, LimitRequestHeaders):
223                 mesg = "Error parsing headers: '%s'" % str(exc)
224             elif isinstance(exc, InvalidProxyLine):
225                 mesg = "'%s'" % str(exc)
226             elif isinstance(exc, ForbiddenProxyRequest):
227                 reason = "Forbidden"
228                 mesg = "Request forbidden"
229                 status_int = 403
230             elif isinstance(exc, InvalidSchemeHeaders):
231                 mesg = "%s" % str(exc)
232             elif isinstance(exc, SSLError):
233                 reason = "Forbidden"
234                 mesg = "'%s'" % str(exc)
235                 status_int = 403
236 
237             msg = "Invalid request from ip={ip}: {error}"
238             self.log.debug(msg.format(ip=addr[0], error=str(exc)))
239         else:
240             if hasattr(req, "uri"):
241                 self.log.exception("Error handling request %s", req.uri)
242             status_int = 500
243             reason = "Internal Server Error"
244             mesg = ""
245 
246         if req is not None:
247             request_time = datetime.now() - request_start
248             environ = default_environ(req, client, self.cfg)
249             environ['REMOTE_ADDR'] = addr[0]
250             environ['REMOTE_PORT'] = str(addr[1])
251             resp = Response(req, client, self.cfg)
252             resp.status = "%s %s" % (status_int, reason)
253             resp.response_length = len(mesg)
254             self.log.access(resp, req, environ, request_time)
255 
256         try:
257             util.write_error(client, status_int, reason, mesg)
258         except:
259             self.log.debug("Failed to send error message.")
260 
261     def handle_winch(self, sig, fname):
262         # Ignore SIGWINCH in worker. Fixes a crash on OpenBSD.
263         self.log.debug("worker: SIGWINCH ignored.")
264
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gunicorn/workers/base.py b/gunicorn/workers/base.py
--- a/gunicorn/workers/base.py
+++ b/gunicorn/workers/base.py
@@ -51,8 +51,13 @@
         self.reloader = None
 
         self.nr = 0
-        jitter = randint(0, cfg.max_requests_jitter)
-        self.max_requests = cfg.max_requests + jitter or sys.maxsize
+
+        if cfg.max_requests > 0:
+            jitter = randint(0, cfg.max_requests_jitter)
+            self.max_requests = cfg.max_requests + jitter
+        else:
+            self.max_requests = sys.maxsize
+
         self.alive = True
         self.log = log
         self.tmp = WorkerTmp(cfg)

{"golden_diff": "diff --git a/gunicorn/workers/base.py b/gunicorn/workers/base.py\n--- a/gunicorn/workers/base.py\n+++ b/gunicorn/workers/base.py\n@@ -51,8 +51,13 @@\n         self.reloader = None\n \n         self.nr = 0\n-        jitter = randint(0, cfg.max_requests_jitter)\n-        self.max_requests = cfg.max_requests + jitter or sys.maxsize\n+\n+        if cfg.max_requests > 0:\n+            jitter = randint(0, cfg.max_requests_jitter)\n+            self.max_requests = cfg.max_requests + jitter\n+        else:\n+            self.max_requests = sys.maxsize\n+\n         self.alive = True\n         self.log = log\n         self.tmp = WorkerTmp(cfg)\n", "issue": "Workers restart with --max-requests=0 when --max-requests-jitter is set to nonzero value\nTo reproduce, start gunicorn like this:\r\n```\r\ngunicorn -w 1 --max-requests=0 --max-requests-jitter=10 -b 0.0.0.0:8000 api:app\r\n```\r\n\r\nThen direct some traffic to it and observe the following log output:\r\n```\r\n[2019-02-05 20:27:23 +0000] [19] [INFO] Starting gunicorn 19.9.0\r\n[2019-02-05 20:27:23 +0000] [19] [INFO] Listening at: http://0.0.0.0:8000 (19)\r\n[2019-02-05 20:27:23 +0000] [19] [INFO] Using worker: sync\r\n[2019-02-05 20:27:23 +0000] [22] [INFO] Booting worker with pid: 22\r\n[2019-02-05 20:27:37 +0000] [22] [INFO] Autorestarting worker after current request.\r\n[2019-02-05 20:27:37 +0000] [22] [INFO] Worker exiting (pid: 22)\r\n[2019-02-05 20:27:37 +0000] [24] [INFO] Booting worker with pid: 24\r\n```\r\n\r\nI expect that `--max-requests-jitter` has no effect when `--max-requests` is set to 0.\n", "before_files": [{"content": "# -*- coding: utf-8 -\n#\n# This file is part of gunicorn released under the MIT license.\n# See the NOTICE for more information.\n\nimport io\nimport os\nimport signal\nimport sys\nimport time\nimport traceback\nfrom datetime import datetime\nfrom random import randint\nfrom ssl import SSLError\n\nfrom gunicorn import util\nfrom gunicorn.http.errors import (\n    ForbiddenProxyRequest, InvalidHeader,\n    InvalidHeaderName, InvalidHTTPVersion,\n    InvalidProxyLine, InvalidRequestLine,\n    InvalidRequestMethod, InvalidSchemeHeaders,\n    LimitRequestHeaders, LimitRequestLine,\n)\nfrom gunicorn.http.wsgi import Response, default_environ\nfrom gunicorn.reloader import reloader_engines\nfrom gunicorn.workers.workertmp import WorkerTmp\n\n\nclass Worker(object):\n\n    SIGNALS = [getattr(signal, \"SIG%s\" % x)\n            for x in \"ABRT HUP QUIT INT TERM USR1 USR2 WINCH CHLD\".split()]\n\n    PIPE = []\n\n    def __init__(self, age, ppid, sockets, app, timeout, cfg, log):\n        \"\"\"\\\n        This is called pre-fork so it shouldn't do anything to the\n        current process. If there's a need to make process wide\n        changes you'll want to do that in ``self.init_process()``.\n        \"\"\"\n        self.age = age\n        self.pid = \"[booting]\"\n        self.ppid = ppid\n        self.sockets = sockets\n        self.app = app\n        self.timeout = timeout\n        self.cfg = cfg\n        self.booted = False\n        self.aborted = False\n        self.reloader = None\n\n        self.nr = 0\n        jitter = randint(0, cfg.max_requests_jitter)\n        self.max_requests = cfg.max_requests + jitter or sys.maxsize\n        self.alive = True\n        self.log = log\n        self.tmp = WorkerTmp(cfg)\n\n    def __str__(self):\n        return \"<Worker %s>\" % self.pid\n\n    def notify(self):\n        \"\"\"\\\n        Your worker subclass must arrange to have this method called\n        once every ``self.timeout`` seconds. If you fail in accomplishing\n        this task, the master process will murder your workers.\n        \"\"\"\n        self.tmp.notify()\n\n    def run(self):\n        \"\"\"\\\n        This is the mainloop of a worker process. You should override\n        this method in a subclass to provide the intended behaviour\n        for your particular evil schemes.\n        \"\"\"\n        raise NotImplementedError()\n\n    def init_process(self):\n        \"\"\"\\\n        If you override this method in a subclass, the last statement\n        in the function should be to call this method with\n        super(MyWorkerClass, self).init_process() so that the ``run()``\n        loop is initiated.\n        \"\"\"\n\n        # set environment' variables\n        if self.cfg.env:\n            for k, v in self.cfg.env.items():\n                os.environ[k] = v\n\n        util.set_owner_process(self.cfg.uid, self.cfg.gid,\n                               initgroups=self.cfg.initgroups)\n\n        # Reseed the random number generator\n        util.seed()\n\n        # For waking ourselves up\n        self.PIPE = os.pipe()\n        for p in self.PIPE:\n            util.set_non_blocking(p)\n            util.close_on_exec(p)\n\n        # Prevent fd inheritance\n        for s in self.sockets:\n            util.close_on_exec(s)\n        util.close_on_exec(self.tmp.fileno())\n\n        self.wait_fds = self.sockets + [self.PIPE[0]]\n\n        self.log.close_on_exec()\n\n        self.init_signals()\n\n        # start the reloader\n        if self.cfg.reload:\n            def changed(fname):\n                self.log.info(\"Worker reloading: %s modified\", fname)\n                self.alive = False\n                self.cfg.worker_int(self)\n                time.sleep(0.1)\n                sys.exit(0)\n\n            reloader_cls = reloader_engines[self.cfg.reload_engine]\n            self.reloader = reloader_cls(extra_files=self.cfg.reload_extra_files,\n                                         callback=changed)\n            self.reloader.start()\n\n        self.load_wsgi()\n        self.cfg.post_worker_init(self)\n\n        # Enter main run loop\n        self.booted = True\n        self.run()\n\n    def load_wsgi(self):\n        try:\n            self.wsgi = self.app.wsgi()\n        except SyntaxError as e:\n            if not self.cfg.reload:\n                raise\n\n            self.log.exception(e)\n\n            # fix from PR #1228\n            # storing the traceback into exc_tb will create a circular reference.\n            # per https://docs.python.org/2/library/sys.html#sys.exc_info warning,\n            # delete the traceback after use.\n            try:\n                _, exc_val, exc_tb = sys.exc_info()\n                self.reloader.add_extra_file(exc_val.filename)\n\n                tb_string = io.StringIO()\n                traceback.print_tb(exc_tb, file=tb_string)\n                self.wsgi = util.make_fail_app(tb_string.getvalue())\n            finally:\n                del exc_tb\n\n    def init_signals(self):\n        # reset signaling\n        for s in self.SIGNALS:\n            signal.signal(s, signal.SIG_DFL)\n        # init new signaling\n        signal.signal(signal.SIGQUIT, self.handle_quit)\n        signal.signal(signal.SIGTERM, self.handle_exit)\n        signal.signal(signal.SIGINT, self.handle_quit)\n        signal.signal(signal.SIGWINCH, self.handle_winch)\n        signal.signal(signal.SIGUSR1, self.handle_usr1)\n        signal.signal(signal.SIGABRT, self.handle_abort)\n\n        # Don't let SIGTERM and SIGUSR1 disturb active requests\n        # by interrupting system calls\n        signal.siginterrupt(signal.SIGTERM, False)\n        signal.siginterrupt(signal.SIGUSR1, False)\n\n        if hasattr(signal, 'set_wakeup_fd'):\n            signal.set_wakeup_fd(self.PIPE[1])\n\n    def handle_usr1(self, sig, frame):\n        self.log.reopen_files()\n\n    def handle_exit(self, sig, frame):\n        self.alive = False\n\n    def handle_quit(self, sig, frame):\n        self.alive = False\n        # worker_int callback\n        self.cfg.worker_int(self)\n        time.sleep(0.1)\n        sys.exit(0)\n\n    def handle_abort(self, sig, frame):\n        self.alive = False\n        self.cfg.worker_abort(self)\n        sys.exit(1)\n\n    def handle_error(self, req, client, addr, exc):\n        request_start = datetime.now()\n        addr = addr or ('', -1)  # unix socket case\n        if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,\n                InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,\n                LimitRequestLine, LimitRequestHeaders,\n                InvalidProxyLine, ForbiddenProxyRequest,\n                InvalidSchemeHeaders,\n                SSLError)):\n\n            status_int = 400\n            reason = \"Bad Request\"\n\n            if isinstance(exc, InvalidRequestLine):\n                mesg = \"Invalid Request Line '%s'\" % str(exc)\n            elif isinstance(exc, InvalidRequestMethod):\n                mesg = \"Invalid Method '%s'\" % str(exc)\n            elif isinstance(exc, InvalidHTTPVersion):\n                mesg = \"Invalid HTTP Version '%s'\" % str(exc)\n            elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):\n                mesg = \"%s\" % str(exc)\n                if not req and hasattr(exc, \"req\"):\n                    req = exc.req  # for access log\n            elif isinstance(exc, LimitRequestLine):\n                mesg = \"%s\" % str(exc)\n            elif isinstance(exc, LimitRequestHeaders):\n                mesg = \"Error parsing headers: '%s'\" % str(exc)\n            elif isinstance(exc, InvalidProxyLine):\n                mesg = \"'%s'\" % str(exc)\n            elif isinstance(exc, ForbiddenProxyRequest):\n                reason = \"Forbidden\"\n                mesg = \"Request forbidden\"\n                status_int = 403\n            elif isinstance(exc, InvalidSchemeHeaders):\n                mesg = \"%s\" % str(exc)\n            elif isinstance(exc, SSLError):\n                reason = \"Forbidden\"\n                mesg = \"'%s'\" % str(exc)\n                status_int = 403\n\n            msg = \"Invalid request from ip={ip}: {error}\"\n            self.log.debug(msg.format(ip=addr[0], error=str(exc)))\n        else:\n            if hasattr(req, \"uri\"):\n                self.log.exception(\"Error handling request %s\", req.uri)\n            status_int = 500\n            reason = \"Internal Server Error\"\n            mesg = \"\"\n\n        if req is not None:\n            request_time = datetime.now() - request_start\n            environ = default_environ(req, client, self.cfg)\n            environ['REMOTE_ADDR'] = addr[0]\n            environ['REMOTE_PORT'] = str(addr[1])\n            resp = Response(req, client, self.cfg)\n            resp.status = \"%s %s\" % (status_int, reason)\n            resp.response_length = len(mesg)\n            self.log.access(resp, req, environ, request_time)\n\n        try:\n            util.write_error(client, status_int, reason, mesg)\n        except:\n            self.log.debug(\"Failed to send error message.\")\n\n    def handle_winch(self, sig, fname):\n        # Ignore SIGWINCH in worker. Fixes a crash on OpenBSD.\n        self.log.debug(\"worker: SIGWINCH ignored.\")\n", "path": "gunicorn/workers/base.py"}], "after_files": [{"content": "# -*- coding: utf-8 -\n#\n# This file is part of gunicorn released under the MIT license.\n# See the NOTICE for more information.\n\nimport io\nimport os\nimport signal\nimport sys\nimport time\nimport traceback\nfrom datetime import datetime\nfrom random import randint\nfrom ssl import SSLError\n\nfrom gunicorn import util\nfrom gunicorn.http.errors import (\n    ForbiddenProxyRequest, InvalidHeader,\n    InvalidHeaderName, InvalidHTTPVersion,\n    InvalidProxyLine, InvalidRequestLine,\n    InvalidRequestMethod, InvalidSchemeHeaders,\n    LimitRequestHeaders, LimitRequestLine,\n)\nfrom gunicorn.http.wsgi import Response, default_environ\nfrom gunicorn.reloader import reloader_engines\nfrom gunicorn.workers.workertmp import WorkerTmp\n\n\nclass Worker(object):\n\n    SIGNALS = [getattr(signal, \"SIG%s\" % x)\n            for x in \"ABRT HUP QUIT INT TERM USR1 USR2 WINCH CHLD\".split()]\n\n    PIPE = []\n\n    def __init__(self, age, ppid, sockets, app, timeout, cfg, log):\n        \"\"\"\\\n        This is called pre-fork so it shouldn't do anything to the\n        current process. If there's a need to make process wide\n        changes you'll want to do that in ``self.init_process()``.\n        \"\"\"\n        self.age = age\n        self.pid = \"[booting]\"\n        self.ppid = ppid\n        self.sockets = sockets\n        self.app = app\n        self.timeout = timeout\n        self.cfg = cfg\n        self.booted = False\n        self.aborted = False\n        self.reloader = None\n\n        self.nr = 0\n\n        if cfg.max_requests > 0:\n            jitter = randint(0, cfg.max_requests_jitter)\n            self.max_requests = cfg.max_requests + jitter\n        else:\n            self.max_requests = sys.maxsize\n\n        self.alive = True\n        self.log = log\n        self.tmp = WorkerTmp(cfg)\n\n    def __str__(self):\n        return \"<Worker %s>\" % self.pid\n\n    def notify(self):\n        \"\"\"\\\n        Your worker subclass must arrange to have this method called\n        once every ``self.timeout`` seconds. If you fail in accomplishing\n        this task, the master process will murder your workers.\n        \"\"\"\n        self.tmp.notify()\n\n    def run(self):\n        \"\"\"\\\n        This is the mainloop of a worker process. You should override\n        this method in a subclass to provide the intended behaviour\n        for your particular evil schemes.\n        \"\"\"\n        raise NotImplementedError()\n\n    def init_process(self):\n        \"\"\"\\\n        If you override this method in a subclass, the last statement\n        in the function should be to call this method with\n        super(MyWorkerClass, self).init_process() so that the ``run()``\n        loop is initiated.\n        \"\"\"\n\n        # set environment' variables\n        if self.cfg.env:\n            for k, v in self.cfg.env.items():\n                os.environ[k] = v\n\n        util.set_owner_process(self.cfg.uid, self.cfg.gid,\n                               initgroups=self.cfg.initgroups)\n\n        # Reseed the random number generator\n        util.seed()\n\n        # For waking ourselves up\n        self.PIPE = os.pipe()\n        for p in self.PIPE:\n            util.set_non_blocking(p)\n            util.close_on_exec(p)\n\n        # Prevent fd inheritance\n        for s in self.sockets:\n            util.close_on_exec(s)\n        util.close_on_exec(self.tmp.fileno())\n\n        self.wait_fds = self.sockets + [self.PIPE[0]]\n\n        self.log.close_on_exec()\n\n        self.init_signals()\n\n        # start the reloader\n        if self.cfg.reload:\n            def changed(fname):\n                self.log.info(\"Worker reloading: %s modified\", fname)\n                self.alive = False\n                self.cfg.worker_int(self)\n                time.sleep(0.1)\n                sys.exit(0)\n\n            reloader_cls = reloader_engines[self.cfg.reload_engine]\n            self.reloader = reloader_cls(extra_files=self.cfg.reload_extra_files,\n                                         callback=changed)\n            self.reloader.start()\n\n        self.load_wsgi()\n        self.cfg.post_worker_init(self)\n\n        # Enter main run loop\n        self.booted = True\n        self.run()\n\n    def load_wsgi(self):\n        try:\n            self.wsgi = self.app.wsgi()\n        except SyntaxError as e:\n            if not self.cfg.reload:\n                raise\n\n            self.log.exception(e)\n\n            # fix from PR #1228\n            # storing the traceback into exc_tb will create a circular reference.\n            # per https://docs.python.org/2/library/sys.html#sys.exc_info warning,\n            # delete the traceback after use.\n            try:\n                _, exc_val, exc_tb = sys.exc_info()\n                self.reloader.add_extra_file(exc_val.filename)\n\n                tb_string = io.StringIO()\n                traceback.print_tb(exc_tb, file=tb_string)\n                self.wsgi = util.make_fail_app(tb_string.getvalue())\n            finally:\n                del exc_tb\n\n    def init_signals(self):\n        # reset signaling\n        for s in self.SIGNALS:\n            signal.signal(s, signal.SIG_DFL)\n        # init new signaling\n        signal.signal(signal.SIGQUIT, self.handle_quit)\n        signal.signal(signal.SIGTERM, self.handle_exit)\n        signal.signal(signal.SIGINT, self.handle_quit)\n        signal.signal(signal.SIGWINCH, self.handle_winch)\n        signal.signal(signal.SIGUSR1, self.handle_usr1)\n        signal.signal(signal.SIGABRT, self.handle_abort)\n\n        # Don't let SIGTERM and SIGUSR1 disturb active requests\n        # by interrupting system calls\n        signal.siginterrupt(signal.SIGTERM, False)\n        signal.siginterrupt(signal.SIGUSR1, False)\n\n        if hasattr(signal, 'set_wakeup_fd'):\n            signal.set_wakeup_fd(self.PIPE[1])\n\n    def handle_usr1(self, sig, frame):\n        self.log.reopen_files()\n\n    def handle_exit(self, sig, frame):\n        self.alive = False\n\n    def handle_quit(self, sig, frame):\n        self.alive = False\n        # worker_int callback\n        self.cfg.worker_int(self)\n        time.sleep(0.1)\n        sys.exit(0)\n\n    def handle_abort(self, sig, frame):\n        self.alive = False\n        self.cfg.worker_abort(self)\n        sys.exit(1)\n\n    def handle_error(self, req, client, addr, exc):\n        request_start = datetime.now()\n        addr = addr or ('', -1)  # unix socket case\n        if isinstance(exc, (InvalidRequestLine, InvalidRequestMethod,\n                InvalidHTTPVersion, InvalidHeader, InvalidHeaderName,\n                LimitRequestLine, LimitRequestHeaders,\n                InvalidProxyLine, ForbiddenProxyRequest,\n                InvalidSchemeHeaders,\n                SSLError)):\n\n            status_int = 400\n            reason = \"Bad Request\"\n\n            if isinstance(exc, InvalidRequestLine):\n                mesg = \"Invalid Request Line '%s'\" % str(exc)\n            elif isinstance(exc, InvalidRequestMethod):\n                mesg = \"Invalid Method '%s'\" % str(exc)\n            elif isinstance(exc, InvalidHTTPVersion):\n                mesg = \"Invalid HTTP Version '%s'\" % str(exc)\n            elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):\n                mesg = \"%s\" % str(exc)\n                if not req and hasattr(exc, \"req\"):\n                    req = exc.req  # for access log\n            elif isinstance(exc, LimitRequestLine):\n                mesg = \"%s\" % str(exc)\n            elif isinstance(exc, LimitRequestHeaders):\n                mesg = \"Error parsing headers: '%s'\" % str(exc)\n            elif isinstance(exc, InvalidProxyLine):\n                mesg = \"'%s'\" % str(exc)\n            elif isinstance(exc, ForbiddenProxyRequest):\n                reason = \"Forbidden\"\n                mesg = \"Request forbidden\"\n                status_int = 403\n            elif isinstance(exc, InvalidSchemeHeaders):\n                mesg = \"%s\" % str(exc)\n            elif isinstance(exc, SSLError):\n                reason = \"Forbidden\"\n                mesg = \"'%s'\" % str(exc)\n                status_int = 403\n\n            msg = \"Invalid request from ip={ip}: {error}\"\n            self.log.debug(msg.format(ip=addr[0], error=str(exc)))\n        else:\n            if hasattr(req, \"uri\"):\n                self.log.exception(\"Error handling request %s\", req.uri)\n            status_int = 500\n            reason = \"Internal Server Error\"\n            mesg = \"\"\n\n        if req is not None:\n            request_time = datetime.now() - request_start\n            environ = default_environ(req, client, self.cfg)\n            environ['REMOTE_ADDR'] = addr[0]\n            environ['REMOTE_PORT'] = str(addr[1])\n            resp = Response(req, client, self.cfg)\n            resp.status = \"%s %s\" % (status_int, reason)\n            resp.response_length = len(mesg)\n            self.log.access(resp, req, environ, request_time)\n\n        try:\n            util.write_error(client, status_int, reason, mesg)\n        except:\n            self.log.debug(\"Failed to send error message.\")\n\n    def handle_winch(self, sig, fname):\n        # Ignore SIGWINCH in worker. Fixes a crash on OpenBSD.\n        self.log.debug(\"worker: SIGWINCH ignored.\")\n", "path": "gunicorn/workers/base.py"}]}