We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Ctrl-C doesn't run shutdown routines
When pressing <kbd>Ctrl</kbd>-<kbd>C</kbd> to interrupt a Sopel instance running in the foreground of an active shell, it simply prints `KeyboardInterrupt` and exits seemingly without calling any of the shutdown routines.

Pressing <kbd>Ctrl</kbd>-<kbd>C</kbd> should behave more or less the same as `sopel --quit`.

Discovered while testing for #1369.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sopel/__init__.py`
Content:
```
1 # coding=utf-8
2 # ASCII ONLY IN THIS FILE THOUGH!!!!!!!
3 # Python does some stupid bullshit of respecting LC_ALL over the encoding on the
4 # file, so in order to undo Python's ridiculous fucking idiocy, we have to have
5 # our own check.
6 
7 # Copyright 2008, Sean B. Palmer, inamidst.com
8 # Copyright 2012, Elsie Powell, http://embolalia.com
9 # Copyright 2012, Elad Alfassa <elad@fedoraproject.org>
10 #
11 # Licensed under the Eiffel Forum License 2.
12 
13 from __future__ import unicode_literals, absolute_import, print_function, division
14 
15 import locale
16 import sys
17 loc = locale.getlocale()
18 if sys.version_info.major > 2:
19     if not loc[1] or 'UTF-8' not in loc[1]:
20         print('WARNING!!! You are running with a non-UTF8 locale environment '
21               'variables (e.g. LC_ALL is set to "C"), which makes Python 3 do '
22               'stupid things. If you get strange errors, please set it to '
23               'something like "en_US.UTF-8".', file=sys.stderr)
24 
25 
26 from collections import namedtuple
27 import os
28 import re
29 import time
30 import traceback
31 import signal
32 
33 __version__ = '6.5.3'
34 
35 
36 def _version_info(version=__version__):
37     regex = re.compile(r'(\d+)\.(\d+)\.(\d+)(?:(a|b|rc)(\d+))?.*')
38     version_groups = regex.match(__version__).groups()
39     major, minor, micro = (int(piece) for piece in version_groups[0:3])
40     level = version_groups[3]
41     serial = int(version_groups[4] or 0)
42     if level == 'a':
43         level = 'alpha'
44     elif level == 'b':
45         level = 'beta'
46     elif level == 'rc':
47         level = 'candidate'
48     elif not level and version_groups[4] is None:
49         level = 'final'
50     else:
51         level = 'alpha'
52     version_type = namedtuple('version_info',
53                               'major, minor, micro, releaselevel, serial')
54     return version_type(major, minor, micro, level, serial)
55 
56 
57 version_info = _version_info()
58 
59 
60 def run(config, pid_file, daemon=False):
61     import sopel.bot as bot
62     import sopel.logger
63     from sopel.tools import stderr
64     delay = 20
65     # Inject ca_certs from config to web for SSL validation of web requests
66     if not config.core.ca_certs:
67         stderr('Could not open CA certificates file. SSL will not '
68                'work properly.')
69 
70     def signal_handler(sig, frame):
71         if sig == signal.SIGUSR1 or sig == signal.SIGTERM:
72             stderr('Got quit signal, shutting down.')
73             p.quit('Closing')
74     while True:
75         try:
76             p = bot.Sopel(config, daemon=daemon)
77             if hasattr(signal, 'SIGUSR1'):
78                 signal.signal(signal.SIGUSR1, signal_handler)
79             if hasattr(signal, 'SIGTERM'):
80                 signal.signal(signal.SIGTERM, signal_handler)
81             sopel.logger.setup_logging(p)
82             p.run(config.core.host, int(config.core.port))
83         except KeyboardInterrupt:
84             break
85         except Exception:  # TODO: Be specific
86             trace = traceback.format_exc()
87             try:
88                 stderr(trace)
89             except Exception:  # TODO: Be specific
90                 pass
91             logfile = open(os.path.join(config.core.logdir, 'exceptions.log'), 'a')
92             logfile.write('Critical exception in core')
93             logfile.write(trace)
94             logfile.write('----------------------------------------\n\n')
95             logfile.close()
96             os.unlink(pid_file)
97             os._exit(1)
98 
99         if not isinstance(delay, int):
100             break
101         if p.hasquit:
102             break
103         stderr('Warning: Disconnected. Reconnecting in %s seconds...' % delay)
104         time.sleep(delay)
105     os.unlink(pid_file)
106     os._exit(0)
107
```
--- 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/sopel/__init__.py b/sopel/__init__.py
--- a/sopel/__init__.py
+++ b/sopel/__init__.py
@@ -68,7 +68,7 @@
                'work properly.')
 
     def signal_handler(sig, frame):
-        if sig == signal.SIGUSR1 or sig == signal.SIGTERM:
+        if sig == signal.SIGUSR1 or sig == signal.SIGTERM or sig == signal.SIGINT:
             stderr('Got quit signal, shutting down.')
             p.quit('Closing')
     while True:
@@ -78,6 +78,8 @@
                 signal.signal(signal.SIGUSR1, signal_handler)
             if hasattr(signal, 'SIGTERM'):
                 signal.signal(signal.SIGTERM, signal_handler)
+            if hasattr(signal, 'SIGINT'):
+                signal.signal(signal.SIGINT, signal_handler)
             sopel.logger.setup_logging(p)
             p.run(config.core.host, int(config.core.port))
         except KeyboardInterrupt:

{"golden_diff": "diff --git a/sopel/__init__.py b/sopel/__init__.py\n--- a/sopel/__init__.py\n+++ b/sopel/__init__.py\n@@ -68,7 +68,7 @@\n                'work properly.')\n \n     def signal_handler(sig, frame):\n-        if sig == signal.SIGUSR1 or sig == signal.SIGTERM:\n+        if sig == signal.SIGUSR1 or sig == signal.SIGTERM or sig == signal.SIGINT:\n             stderr('Got quit signal, shutting down.')\n             p.quit('Closing')\n     while True:\n@@ -78,6 +78,8 @@\n                 signal.signal(signal.SIGUSR1, signal_handler)\n             if hasattr(signal, 'SIGTERM'):\n                 signal.signal(signal.SIGTERM, signal_handler)\n+            if hasattr(signal, 'SIGINT'):\n+                signal.signal(signal.SIGINT, signal_handler)\n             sopel.logger.setup_logging(p)\n             p.run(config.core.host, int(config.core.port))\n         except KeyboardInterrupt:\n", "issue": "Ctrl-C doesn't run shutdown routines\nWhen pressing <kbd>Ctrl</kbd>-<kbd>C</kbd> to interrupt a Sopel instance running in the foreground of an active shell, it simply prints `KeyboardInterrupt` and exits seemingly without calling any of the shutdown routines.\r\n\r\nPressing <kbd>Ctrl</kbd>-<kbd>C</kbd> should behave more or less the same as `sopel --quit`.\r\n\r\nDiscovered while testing for #1369.\n", "before_files": [{"content": "# coding=utf-8\n# ASCII ONLY IN THIS FILE THOUGH!!!!!!!\n# Python does some stupid bullshit of respecting LC_ALL over the encoding on the\n# file, so in order to undo Python's ridiculous fucking idiocy, we have to have\n# our own check.\n\n# Copyright 2008, Sean B. Palmer, inamidst.com\n# Copyright 2012, Elsie Powell, http://embolalia.com\n# Copyright 2012, Elad Alfassa <elad@fedoraproject.org>\n#\n# Licensed under the Eiffel Forum License 2.\n\nfrom __future__ import unicode_literals, absolute_import, print_function, division\n\nimport locale\nimport sys\nloc = locale.getlocale()\nif sys.version_info.major > 2:\n    if not loc[1] or 'UTF-8' not in loc[1]:\n        print('WARNING!!! You are running with a non-UTF8 locale environment '\n              'variables (e.g. LC_ALL is set to \"C\"), which makes Python 3 do '\n              'stupid things. If you get strange errors, please set it to '\n              'something like \"en_US.UTF-8\".', file=sys.stderr)\n\n\nfrom collections import namedtuple\nimport os\nimport re\nimport time\nimport traceback\nimport signal\n\n__version__ = '6.5.3'\n\n\ndef _version_info(version=__version__):\n    regex = re.compile(r'(\\d+)\\.(\\d+)\\.(\\d+)(?:(a|b|rc)(\\d+))?.*')\n    version_groups = regex.match(__version__).groups()\n    major, minor, micro = (int(piece) for piece in version_groups[0:3])\n    level = version_groups[3]\n    serial = int(version_groups[4] or 0)\n    if level == 'a':\n        level = 'alpha'\n    elif level == 'b':\n        level = 'beta'\n    elif level == 'rc':\n        level = 'candidate'\n    elif not level and version_groups[4] is None:\n        level = 'final'\n    else:\n        level = 'alpha'\n    version_type = namedtuple('version_info',\n                              'major, minor, micro, releaselevel, serial')\n    return version_type(major, minor, micro, level, serial)\n\n\nversion_info = _version_info()\n\n\ndef run(config, pid_file, daemon=False):\n    import sopel.bot as bot\n    import sopel.logger\n    from sopel.tools import stderr\n    delay = 20\n    # Inject ca_certs from config to web for SSL validation of web requests\n    if not config.core.ca_certs:\n        stderr('Could not open CA certificates file. SSL will not '\n               'work properly.')\n\n    def signal_handler(sig, frame):\n        if sig == signal.SIGUSR1 or sig == signal.SIGTERM:\n            stderr('Got quit signal, shutting down.')\n            p.quit('Closing')\n    while True:\n        try:\n            p = bot.Sopel(config, daemon=daemon)\n            if hasattr(signal, 'SIGUSR1'):\n                signal.signal(signal.SIGUSR1, signal_handler)\n            if hasattr(signal, 'SIGTERM'):\n                signal.signal(signal.SIGTERM, signal_handler)\n            sopel.logger.setup_logging(p)\n            p.run(config.core.host, int(config.core.port))\n        except KeyboardInterrupt:\n            break\n        except Exception:  # TODO: Be specific\n            trace = traceback.format_exc()\n            try:\n                stderr(trace)\n            except Exception:  # TODO: Be specific\n                pass\n            logfile = open(os.path.join(config.core.logdir, 'exceptions.log'), 'a')\n            logfile.write('Critical exception in core')\n            logfile.write(trace)\n            logfile.write('----------------------------------------\\n\\n')\n            logfile.close()\n            os.unlink(pid_file)\n            os._exit(1)\n\n        if not isinstance(delay, int):\n            break\n        if p.hasquit:\n            break\n        stderr('Warning: Disconnected. Reconnecting in %s seconds...' % delay)\n        time.sleep(delay)\n    os.unlink(pid_file)\n    os._exit(0)\n", "path": "sopel/__init__.py"}], "after_files": [{"content": "# coding=utf-8\n# ASCII ONLY IN THIS FILE THOUGH!!!!!!!\n# Python does some stupid bullshit of respecting LC_ALL over the encoding on the\n# file, so in order to undo Python's ridiculous fucking idiocy, we have to have\n# our own check.\n\n# Copyright 2008, Sean B. Palmer, inamidst.com\n# Copyright 2012, Elsie Powell, http://embolalia.com\n# Copyright 2012, Elad Alfassa <elad@fedoraproject.org>\n#\n# Licensed under the Eiffel Forum License 2.\n\nfrom __future__ import unicode_literals, absolute_import, print_function, division\n\nimport locale\nimport sys\nloc = locale.getlocale()\nif sys.version_info.major > 2:\n    if not loc[1] or 'UTF-8' not in loc[1]:\n        print('WARNING!!! You are running with a non-UTF8 locale environment '\n              'variables (e.g. LC_ALL is set to \"C\"), which makes Python 3 do '\n              'stupid things. If you get strange errors, please set it to '\n              'something like \"en_US.UTF-8\".', file=sys.stderr)\n\n\nfrom collections import namedtuple\nimport os\nimport re\nimport time\nimport traceback\nimport signal\n\n__version__ = '6.5.3'\n\n\ndef _version_info(version=__version__):\n    regex = re.compile(r'(\\d+)\\.(\\d+)\\.(\\d+)(?:(a|b|rc)(\\d+))?.*')\n    version_groups = regex.match(__version__).groups()\n    major, minor, micro = (int(piece) for piece in version_groups[0:3])\n    level = version_groups[3]\n    serial = int(version_groups[4] or 0)\n    if level == 'a':\n        level = 'alpha'\n    elif level == 'b':\n        level = 'beta'\n    elif level == 'rc':\n        level = 'candidate'\n    elif not level and version_groups[4] is None:\n        level = 'final'\n    else:\n        level = 'alpha'\n    version_type = namedtuple('version_info',\n                              'major, minor, micro, releaselevel, serial')\n    return version_type(major, minor, micro, level, serial)\n\n\nversion_info = _version_info()\n\n\ndef run(config, pid_file, daemon=False):\n    import sopel.bot as bot\n    import sopel.logger\n    from sopel.tools import stderr\n    delay = 20\n    # Inject ca_certs from config to web for SSL validation of web requests\n    if not config.core.ca_certs:\n        stderr('Could not open CA certificates file. SSL will not '\n               'work properly.')\n\n    def signal_handler(sig, frame):\n        if sig == signal.SIGUSR1 or sig == signal.SIGTERM or sig == signal.SIGINT:\n            stderr('Got quit signal, shutting down.')\n            p.quit('Closing')\n    while True:\n        try:\n            p = bot.Sopel(config, daemon=daemon)\n            if hasattr(signal, 'SIGUSR1'):\n                signal.signal(signal.SIGUSR1, signal_handler)\n            if hasattr(signal, 'SIGTERM'):\n                signal.signal(signal.SIGTERM, signal_handler)\n            if hasattr(signal, 'SIGINT'):\n                signal.signal(signal.SIGINT, signal_handler)\n            sopel.logger.setup_logging(p)\n            p.run(config.core.host, int(config.core.port))\n        except KeyboardInterrupt:\n            break\n        except Exception:  # TODO: Be specific\n            trace = traceback.format_exc()\n            try:\n                stderr(trace)\n            except Exception:  # TODO: Be specific\n                pass\n            logfile = open(os.path.join(config.core.logdir, 'exceptions.log'), 'a')\n            logfile.write('Critical exception in core')\n            logfile.write(trace)\n            logfile.write('----------------------------------------\\n\\n')\n            logfile.close()\n            os.unlink(pid_file)\n            os._exit(1)\n\n        if not isinstance(delay, int):\n            break\n        if p.hasquit:\n            break\n        stderr('Warning: Disconnected. Reconnecting in %s seconds...' % delay)\n        time.sleep(delay)\n    os.unlink(pid_file)\n    os._exit(0)\n", "path": "sopel/__init__.py"}]}