prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Signal handlers
  In the worker class
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `uvicorn/worker.py`
  Content:
  ```
  1 import asyncio
  2 import functools
  3 
  4 import uvloop
  5 
  6 from gunicorn.workers.base import Worker
  7 from uvicorn.protocols import http
  8 
  9 
  10 class UvicornWorker(Worker):
  11     """
  12     A worker class for Gunicorn that interfaces with an ASGI consumer callable,
  13     rather than a WSGI callable.
  14 
  15     We use a couple of packages from MagicStack in order to achieve an
  16     extremely high-throughput and low-latency implementation:
  17 
  18     * `uvloop` as the event loop policy.
  19     * `httptools` as the HTTP request parser.
  20     """
  21 
  22     def init_process(self):
  23         # Close any existing event loop before setting a
  24         # new policy.
  25         asyncio.get_event_loop().close()
  26 
  27         # Setup uvloop policy, so that every
  28         # asyncio.get_event_loop() will create an instance
  29         # of uvloop event loop.
  30         asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
  31 
  32         super().init_process()
  33 
  34     def run(self):
  35         loop = asyncio.get_event_loop()
  36         loop.create_task(self.create_servers(loop))
  37         loop.create_task(tick(loop, self.notify))
  38         loop.run_forever()
  39 
  40     async def create_servers(self, loop):
  41         cfg = self.cfg
  42         consumer = self.wsgi
  43 
  44         for sock in self.sockets:
  45             protocol = functools.partial(
  46                 http.HttpProtocol,
  47                 consumer=consumer, loop=loop, sock=sock, cfg=cfg
  48             )
  49             await loop.create_server(protocol, sock=sock)
  50 
  51 
  52 async def tick(loop, notify):
  53     cycle = 0
  54     while True:
  55         http.set_time_and_date()
  56         cycle = (cycle + 1) % 10
  57         if cycle == 0:
  58             notify()
  59         await asyncio.sleep(1)
  60
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/uvicorn/worker.py b/uvicorn/worker.py
  --- a/uvicorn/worker.py
  +++ b/uvicorn/worker.py
  @@ -1,5 +1,7 @@
   import asyncio
   import functools
  +import signal
  +import sys
   
   import uvloop
   
  @@ -19,6 +21,11 @@
       * `httptools` as the HTTP request parser.
       """
   
  +    def __init__(self, *args, **kwargs):  # pragma: no cover
  +        super().__init__(*args, **kwargs)
  +        self.servers = []
  +        self.exit_code = 0
  +
       def init_process(self):
           # Close any existing event loop before setting a
           # new policy.
  @@ -34,8 +41,45 @@
       def run(self):
           loop = asyncio.get_event_loop()
           loop.create_task(self.create_servers(loop))
  -        loop.create_task(tick(loop, self.notify))
  +        loop.create_task(self.tick(loop))
           loop.run_forever()
  +        sys.exit(self.exit_code)
  +
  +    def init_signals(self):
  +        # Set up signals through the event loop API.
  +        loop = asyncio.get_event_loop()
  +
  +        loop.add_signal_handler(signal.SIGQUIT, self.handle_quit,
  +                                signal.SIGQUIT, None)
  +
  +        loop.add_signal_handler(signal.SIGTERM, self.handle_exit,
  +                                signal.SIGTERM, None)
  +
  +        loop.add_signal_handler(signal.SIGINT, self.handle_quit,
  +                                signal.SIGINT, None)
  +
  +        loop.add_signal_handler(signal.SIGWINCH, self.handle_winch,
  +                                signal.SIGWINCH, None)
  +
  +        loop.add_signal_handler(signal.SIGUSR1, self.handle_usr1,
  +                                signal.SIGUSR1, None)
  +
  +        loop.add_signal_handler(signal.SIGABRT, self.handle_abort,
  +                                signal.SIGABRT, None)
  +
  +        # Don't let SIGTERM and SIGUSR1 disturb active requests
  +        # by interrupting system calls
  +        signal.siginterrupt(signal.SIGTERM, False)
  +        signal.siginterrupt(signal.SIGUSR1, False)
  +
  +    def handle_quit(self, sig, frame):
  +        self.alive = False
  +        self.cfg.worker_int(self)
  +
  +    def handle_abort(self, sig, frame):
  +        self.alive = False
  +        self.exit_code = 1
  +        self.cfg.worker_abort(self)
   
       async def create_servers(self, loop):
           cfg = self.cfg
  @@ -46,14 +90,19 @@
                   http.HttpProtocol,
                   consumer=consumer, loop=loop, sock=sock, cfg=cfg
               )
  -            await loop.create_server(protocol, sock=sock)
  +            server = await loop.create_server(protocol, sock=sock)
  +            self.servers.append(server)
   
  +    async def tick(self, loop):
  +        cycle = 0
  +        while self.alive:
  +            http.set_time_and_date()
  +            cycle = (cycle + 1) % 10
  +            if cycle == 0:
  +                self.notify()
  +            await asyncio.sleep(1)
   
  -async def tick(loop, notify):
  -    cycle = 0
  -    while True:
  -        http.set_time_and_date()
  -        cycle = (cycle + 1) % 10
  -        if cycle == 0:
  -            notify()
  -        await asyncio.sleep(1)
  +        for server in self.servers:
  +            server.close()
  +            await server.wait_closed()
  +        loop.stop()
  
verification_info: {"golden_diff": "diff --git a/uvicorn/worker.py b/uvicorn/worker.py\n--- a/uvicorn/worker.py\n+++ b/uvicorn/worker.py\n@@ -1,5 +1,7 @@\n import asyncio\n import functools\n+import signal\n+import sys\n \n import uvloop\n \n@@ -19,6 +21,11 @@\n     * `httptools` as the HTTP request parser.\n     \"\"\"\n \n+    def __init__(self, *args, **kwargs):  # pragma: no cover\n+        super().__init__(*args, **kwargs)\n+        self.servers = []\n+        self.exit_code = 0\n+\n     def init_process(self):\n         # Close any existing event loop before setting a\n         # new policy.\n@@ -34,8 +41,45 @@\n     def run(self):\n         loop = asyncio.get_event_loop()\n         loop.create_task(self.create_servers(loop))\n-        loop.create_task(tick(loop, self.notify))\n+        loop.create_task(self.tick(loop))\n         loop.run_forever()\n+        sys.exit(self.exit_code)\n+\n+    def init_signals(self):\n+        # Set up signals through the event loop API.\n+        loop = asyncio.get_event_loop()\n+\n+        loop.add_signal_handler(signal.SIGQUIT, self.handle_quit,\n+                                signal.SIGQUIT, None)\n+\n+        loop.add_signal_handler(signal.SIGTERM, self.handle_exit,\n+                                signal.SIGTERM, None)\n+\n+        loop.add_signal_handler(signal.SIGINT, self.handle_quit,\n+                                signal.SIGINT, None)\n+\n+        loop.add_signal_handler(signal.SIGWINCH, self.handle_winch,\n+                                signal.SIGWINCH, None)\n+\n+        loop.add_signal_handler(signal.SIGUSR1, self.handle_usr1,\n+                                signal.SIGUSR1, None)\n+\n+        loop.add_signal_handler(signal.SIGABRT, self.handle_abort,\n+                                signal.SIGABRT, None)\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+    def handle_quit(self, sig, frame):\n+        self.alive = False\n+        self.cfg.worker_int(self)\n+\n+    def handle_abort(self, sig, frame):\n+        self.alive = False\n+        self.exit_code = 1\n+        self.cfg.worker_abort(self)\n \n     async def create_servers(self, loop):\n         cfg = self.cfg\n@@ -46,14 +90,19 @@\n                 http.HttpProtocol,\n                 consumer=consumer, loop=loop, sock=sock, cfg=cfg\n             )\n-            await loop.create_server(protocol, sock=sock)\n+            server = await loop.create_server(protocol, sock=sock)\n+            self.servers.append(server)\n \n+    async def tick(self, loop):\n+        cycle = 0\n+        while self.alive:\n+            http.set_time_and_date()\n+            cycle = (cycle + 1) % 10\n+            if cycle == 0:\n+                self.notify()\n+            await asyncio.sleep(1)\n \n-async def tick(loop, notify):\n-    cycle = 0\n-    while True:\n-        http.set_time_and_date()\n-        cycle = (cycle + 1) % 10\n-        if cycle == 0:\n-            notify()\n-        await asyncio.sleep(1)\n+        for server in self.servers:\n+            server.close()\n+            await server.wait_closed()\n+        loop.stop()\n", "issue": "Signal handlers\nIn the worker class\n", "before_files": [{"content": "import asyncio\nimport functools\n\nimport uvloop\n\nfrom gunicorn.workers.base import Worker\nfrom uvicorn.protocols import http\n\n\nclass UvicornWorker(Worker):\n    \"\"\"\n    A worker class for Gunicorn that interfaces with an ASGI consumer callable,\n    rather than a WSGI callable.\n\n    We use a couple of packages from MagicStack in order to achieve an\n    extremely high-throughput and low-latency implementation:\n\n    * `uvloop` as the event loop policy.\n    * `httptools` as the HTTP request parser.\n    \"\"\"\n\n    def init_process(self):\n        # Close any existing event loop before setting a\n        # new policy.\n        asyncio.get_event_loop().close()\n\n        # Setup uvloop policy, so that every\n        # asyncio.get_event_loop() will create an instance\n        # of uvloop event loop.\n        asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())\n\n        super().init_process()\n\n    def run(self):\n        loop = asyncio.get_event_loop()\n        loop.create_task(self.create_servers(loop))\n        loop.create_task(tick(loop, self.notify))\n        loop.run_forever()\n\n    async def create_servers(self, loop):\n        cfg = self.cfg\n        consumer = self.wsgi\n\n        for sock in self.sockets:\n            protocol = functools.partial(\n                http.HttpProtocol,\n                consumer=consumer, loop=loop, sock=sock, cfg=cfg\n            )\n            await loop.create_server(protocol, sock=sock)\n\n\nasync def tick(loop, notify):\n    cycle = 0\n    while True:\n        http.set_time_and_date()\n        cycle = (cycle + 1) % 10\n        if cycle == 0:\n            notify()\n        await asyncio.sleep(1)\n", "path": "uvicorn/worker.py"}], "after_files": [{"content": "import asyncio\nimport functools\nimport signal\nimport sys\n\nimport uvloop\n\nfrom gunicorn.workers.base import Worker\nfrom uvicorn.protocols import http\n\n\nclass UvicornWorker(Worker):\n    \"\"\"\n    A worker class for Gunicorn that interfaces with an ASGI consumer callable,\n    rather than a WSGI callable.\n\n    We use a couple of packages from MagicStack in order to achieve an\n    extremely high-throughput and low-latency implementation:\n\n    * `uvloop` as the event loop policy.\n    * `httptools` as the HTTP request parser.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):  # pragma: no cover\n        super().__init__(*args, **kwargs)\n        self.servers = []\n        self.exit_code = 0\n\n    def init_process(self):\n        # Close any existing event loop before setting a\n        # new policy.\n        asyncio.get_event_loop().close()\n\n        # Setup uvloop policy, so that every\n        # asyncio.get_event_loop() will create an instance\n        # of uvloop event loop.\n        asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())\n\n        super().init_process()\n\n    def run(self):\n        loop = asyncio.get_event_loop()\n        loop.create_task(self.create_servers(loop))\n        loop.create_task(self.tick(loop))\n        loop.run_forever()\n        sys.exit(self.exit_code)\n\n    def init_signals(self):\n        # Set up signals through the event loop API.\n        loop = asyncio.get_event_loop()\n\n        loop.add_signal_handler(signal.SIGQUIT, self.handle_quit,\n                                signal.SIGQUIT, None)\n\n        loop.add_signal_handler(signal.SIGTERM, self.handle_exit,\n                                signal.SIGTERM, None)\n\n        loop.add_signal_handler(signal.SIGINT, self.handle_quit,\n                                signal.SIGINT, None)\n\n        loop.add_signal_handler(signal.SIGWINCH, self.handle_winch,\n                                signal.SIGWINCH, None)\n\n        loop.add_signal_handler(signal.SIGUSR1, self.handle_usr1,\n                                signal.SIGUSR1, None)\n\n        loop.add_signal_handler(signal.SIGABRT, self.handle_abort,\n                                signal.SIGABRT, None)\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    def handle_quit(self, sig, frame):\n        self.alive = False\n        self.cfg.worker_int(self)\n\n    def handle_abort(self, sig, frame):\n        self.alive = False\n        self.exit_code = 1\n        self.cfg.worker_abort(self)\n\n    async def create_servers(self, loop):\n        cfg = self.cfg\n        consumer = self.wsgi\n\n        for sock in self.sockets:\n            protocol = functools.partial(\n                http.HttpProtocol,\n                consumer=consumer, loop=loop, sock=sock, cfg=cfg\n            )\n            server = await loop.create_server(protocol, sock=sock)\n            self.servers.append(server)\n\n    async def tick(self, loop):\n        cycle = 0\n        while self.alive:\n            http.set_time_and_date()\n            cycle = (cycle + 1) % 10\n            if cycle == 0:\n                self.notify()\n            await asyncio.sleep(1)\n\n        for server in self.servers:\n            server.close()\n            await server.wait_closed()\n        loop.stop()\n", "path": "uvicorn/worker.py"}]}