We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Ubuntu 21.10 (Impish Indri) has reached end of life as of July 14, 2022
See https://lists.ubuntu.com/archives/ubuntu-announce/2022-July/000281.html

I don't think we have good docs for removing a distribution, but should be the opposite of [gitlab.matrix.org/new-vector/internal/-/wikis/Synapse-Debian-Packages#adding-a-new-distribution](https://gitlab.matrix.org/new-vector/internal/-/wikis/Synapse-Debian-Packages#adding-a-new-distribution).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scripts-dev/build_debian_packages.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 # Build the Debian packages using Docker images.
4 #
5 # This script builds the Docker images and then executes them sequentially, each
6 # one building a Debian package for the targeted operating system. It is
7 # designed to be a "single command" to produce all the images.
8 #
9 # By default, builds for all known distributions, but a list of distributions
10 # can be passed on the commandline for debugging.
11 
12 import argparse
13 import json
14 import os
15 import signal
16 import subprocess
17 import sys
18 import threading
19 from concurrent.futures import ThreadPoolExecutor
20 from types import FrameType
21 from typing import Collection, Optional, Sequence, Set
22 
23 DISTS = (
24     "debian:buster",  # oldstable: EOL 2022-08
25     "debian:bullseye",
26     "debian:bookworm",
27     "debian:sid",
28     "ubuntu:focal",  # 20.04 LTS (our EOL forced by Py38 on 2024-10-14)
29     "ubuntu:impish",  # 21.10  (EOL 2022-07)
30     "ubuntu:jammy",  # 22.04 LTS (EOL 2027-04)
31 )
32 
33 DESC = """\
34 Builds .debs for synapse, using a Docker image for the build environment.
35 
36 By default, builds for all known distributions, but a list of distributions
37 can be passed on the commandline for debugging.
38 """
39 
40 projdir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
41 
42 
43 class Builder(object):
44     def __init__(
45         self,
46         redirect_stdout: bool = False,
47         docker_build_args: Optional[Sequence[str]] = None,
48     ):
49         self.redirect_stdout = redirect_stdout
50         self._docker_build_args = tuple(docker_build_args or ())
51         self.active_containers: Set[str] = set()
52         self._lock = threading.Lock()
53         self._failed = False
54 
55     def run_build(self, dist: str, skip_tests: bool = False) -> None:
56         """Build deb for a single distribution"""
57 
58         if self._failed:
59             print("not building %s due to earlier failure" % (dist,))
60             raise Exception("failed")
61 
62         try:
63             self._inner_build(dist, skip_tests)
64         except Exception as e:
65             print("build of %s failed: %s" % (dist, e), file=sys.stderr)
66             self._failed = True
67             raise
68 
69     def _inner_build(self, dist: str, skip_tests: bool = False) -> None:
70         tag = dist.split(":", 1)[1]
71 
72         # Make the dir where the debs will live.
73         #
74         # Note that we deliberately put this outside the source tree, otherwise
75         # we tend to get source packages which are full of debs. (We could hack
76         # around that with more magic in the build_debian.sh script, but that
77         # doesn't solve the problem for natively-run dpkg-buildpakage).
78         debsdir = os.path.join(projdir, "../debs")
79         os.makedirs(debsdir, exist_ok=True)
80 
81         if self.redirect_stdout:
82             logfile = os.path.join(debsdir, "%s.buildlog" % (tag,))
83             print("building %s: directing output to %s" % (dist, logfile))
84             stdout = open(logfile, "w")
85         else:
86             stdout = None
87 
88         # first build a docker image for the build environment
89         build_args = (
90             (
91                 "docker",
92                 "build",
93                 "--tag",
94                 "dh-venv-builder:" + tag,
95                 "--build-arg",
96                 "distro=" + dist,
97                 "-f",
98                 "docker/Dockerfile-dhvirtualenv",
99             )
100             + self._docker_build_args
101             + ("docker",)
102         )
103 
104         subprocess.check_call(
105             build_args,
106             stdout=stdout,
107             stderr=subprocess.STDOUT,
108             cwd=projdir,
109         )
110 
111         container_name = "synapse_build_" + tag
112         with self._lock:
113             self.active_containers.add(container_name)
114 
115         # then run the build itself
116         subprocess.check_call(
117             [
118                 "docker",
119                 "run",
120                 "--rm",
121                 "--name",
122                 container_name,
123                 "--volume=" + projdir + ":/synapse/source:ro",
124                 "--volume=" + debsdir + ":/debs",
125                 "-e",
126                 "TARGET_USERID=%i" % (os.getuid(),),
127                 "-e",
128                 "TARGET_GROUPID=%i" % (os.getgid(),),
129                 "-e",
130                 "DEB_BUILD_OPTIONS=%s" % ("nocheck" if skip_tests else ""),
131                 "dh-venv-builder:" + tag,
132             ],
133             stdout=stdout,
134             stderr=subprocess.STDOUT,
135         )
136 
137         with self._lock:
138             self.active_containers.remove(container_name)
139 
140         if stdout is not None:
141             stdout.close()
142             print("Completed build of %s" % (dist,))
143 
144     def kill_containers(self) -> None:
145         with self._lock:
146             active = list(self.active_containers)
147 
148         for c in active:
149             print("killing container %s" % (c,))
150             subprocess.run(
151                 [
152                     "docker",
153                     "kill",
154                     c,
155                 ],
156                 stdout=subprocess.DEVNULL,
157             )
158             with self._lock:
159                 self.active_containers.remove(c)
160 
161 
162 def run_builds(
163     builder: Builder, dists: Collection[str], jobs: int = 1, skip_tests: bool = False
164 ) -> None:
165     def sig(signum: int, _frame: Optional[FrameType]) -> None:
166         print("Caught SIGINT")
167         builder.kill_containers()
168 
169     signal.signal(signal.SIGINT, sig)
170 
171     with ThreadPoolExecutor(max_workers=jobs) as e:
172         res = e.map(lambda dist: builder.run_build(dist, skip_tests), dists)
173 
174     # make sure we consume the iterable so that exceptions are raised.
175     for _ in res:
176         pass
177 
178 
179 if __name__ == "__main__":
180     parser = argparse.ArgumentParser(
181         description=DESC,
182     )
183     parser.add_argument(
184         "-j",
185         "--jobs",
186         type=int,
187         default=1,
188         help="specify the number of builds to run in parallel",
189     )
190     parser.add_argument(
191         "--no-check",
192         action="store_true",
193         help="skip running tests after building",
194     )
195     parser.add_argument(
196         "--docker-build-arg",
197         action="append",
198         help="specify an argument to pass to docker build",
199     )
200     parser.add_argument(
201         "--show-dists-json",
202         action="store_true",
203         help="instead of building the packages, just list the dists to build for, as a json array",
204     )
205     parser.add_argument(
206         "dist",
207         nargs="*",
208         default=DISTS,
209         help="a list of distributions to build for. Default: %(default)s",
210     )
211     args = parser.parse_args()
212     if args.show_dists_json:
213         print(json.dumps(DISTS))
214     else:
215         builder = Builder(
216             redirect_stdout=(args.jobs > 1), docker_build_args=args.docker_build_arg
217         )
218         run_builds(
219             builder,
220             dists=args.dist,
221             jobs=args.jobs,
222             skip_tests=args.no_check,
223         )
224
```
--- 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/scripts-dev/build_debian_packages.py b/scripts-dev/build_debian_packages.py
--- a/scripts-dev/build_debian_packages.py
+++ b/scripts-dev/build_debian_packages.py
@@ -26,7 +26,6 @@
     "debian:bookworm",
     "debian:sid",
     "ubuntu:focal",  # 20.04 LTS (our EOL forced by Py38 on 2024-10-14)
-    "ubuntu:impish",  # 21.10  (EOL 2022-07)
     "ubuntu:jammy",  # 22.04 LTS (EOL 2027-04)
 )

{"golden_diff": "diff --git a/scripts-dev/build_debian_packages.py b/scripts-dev/build_debian_packages.py\n--- a/scripts-dev/build_debian_packages.py\n+++ b/scripts-dev/build_debian_packages.py\n@@ -26,7 +26,6 @@\n     \"debian:bookworm\",\n     \"debian:sid\",\n     \"ubuntu:focal\",  # 20.04 LTS (our EOL forced by Py38 on 2024-10-14)\n-    \"ubuntu:impish\",  # 21.10  (EOL 2022-07)\n     \"ubuntu:jammy\",  # 22.04 LTS (EOL 2027-04)\n )\n", "issue": "Ubuntu 21.10 (Impish Indri) has reached end of life as of July 14, 2022\nSee https://lists.ubuntu.com/archives/ubuntu-announce/2022-July/000281.html\r\n\r\nI don't think we have good docs for removing a distribution, but should be the opposite of [gitlab.matrix.org/new-vector/internal/-/wikis/Synapse-Debian-Packages#adding-a-new-distribution](https://gitlab.matrix.org/new-vector/internal/-/wikis/Synapse-Debian-Packages#adding-a-new-distribution).\n", "before_files": [{"content": "#!/usr/bin/env python3\n\n# Build the Debian packages using Docker images.\n#\n# This script builds the Docker images and then executes them sequentially, each\n# one building a Debian package for the targeted operating system. It is\n# designed to be a \"single command\" to produce all the images.\n#\n# By default, builds for all known distributions, but a list of distributions\n# can be passed on the commandline for debugging.\n\nimport argparse\nimport json\nimport os\nimport signal\nimport subprocess\nimport sys\nimport threading\nfrom concurrent.futures import ThreadPoolExecutor\nfrom types import FrameType\nfrom typing import Collection, Optional, Sequence, Set\n\nDISTS = (\n    \"debian:buster\",  # oldstable: EOL 2022-08\n    \"debian:bullseye\",\n    \"debian:bookworm\",\n    \"debian:sid\",\n    \"ubuntu:focal\",  # 20.04 LTS (our EOL forced by Py38 on 2024-10-14)\n    \"ubuntu:impish\",  # 21.10  (EOL 2022-07)\n    \"ubuntu:jammy\",  # 22.04 LTS (EOL 2027-04)\n)\n\nDESC = \"\"\"\\\nBuilds .debs for synapse, using a Docker image for the build environment.\n\nBy default, builds for all known distributions, but a list of distributions\ncan be passed on the commandline for debugging.\n\"\"\"\n\nprojdir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))\n\n\nclass Builder(object):\n    def __init__(\n        self,\n        redirect_stdout: bool = False,\n        docker_build_args: Optional[Sequence[str]] = None,\n    ):\n        self.redirect_stdout = redirect_stdout\n        self._docker_build_args = tuple(docker_build_args or ())\n        self.active_containers: Set[str] = set()\n        self._lock = threading.Lock()\n        self._failed = False\n\n    def run_build(self, dist: str, skip_tests: bool = False) -> None:\n        \"\"\"Build deb for a single distribution\"\"\"\n\n        if self._failed:\n            print(\"not building %s due to earlier failure\" % (dist,))\n            raise Exception(\"failed\")\n\n        try:\n            self._inner_build(dist, skip_tests)\n        except Exception as e:\n            print(\"build of %s failed: %s\" % (dist, e), file=sys.stderr)\n            self._failed = True\n            raise\n\n    def _inner_build(self, dist: str, skip_tests: bool = False) -> None:\n        tag = dist.split(\":\", 1)[1]\n\n        # Make the dir where the debs will live.\n        #\n        # Note that we deliberately put this outside the source tree, otherwise\n        # we tend to get source packages which are full of debs. (We could hack\n        # around that with more magic in the build_debian.sh script, but that\n        # doesn't solve the problem for natively-run dpkg-buildpakage).\n        debsdir = os.path.join(projdir, \"../debs\")\n        os.makedirs(debsdir, exist_ok=True)\n\n        if self.redirect_stdout:\n            logfile = os.path.join(debsdir, \"%s.buildlog\" % (tag,))\n            print(\"building %s: directing output to %s\" % (dist, logfile))\n            stdout = open(logfile, \"w\")\n        else:\n            stdout = None\n\n        # first build a docker image for the build environment\n        build_args = (\n            (\n                \"docker\",\n                \"build\",\n                \"--tag\",\n                \"dh-venv-builder:\" + tag,\n                \"--build-arg\",\n                \"distro=\" + dist,\n                \"-f\",\n                \"docker/Dockerfile-dhvirtualenv\",\n            )\n            + self._docker_build_args\n            + (\"docker\",)\n        )\n\n        subprocess.check_call(\n            build_args,\n            stdout=stdout,\n            stderr=subprocess.STDOUT,\n            cwd=projdir,\n        )\n\n        container_name = \"synapse_build_\" + tag\n        with self._lock:\n            self.active_containers.add(container_name)\n\n        # then run the build itself\n        subprocess.check_call(\n            [\n                \"docker\",\n                \"run\",\n                \"--rm\",\n                \"--name\",\n                container_name,\n                \"--volume=\" + projdir + \":/synapse/source:ro\",\n                \"--volume=\" + debsdir + \":/debs\",\n                \"-e\",\n                \"TARGET_USERID=%i\" % (os.getuid(),),\n                \"-e\",\n                \"TARGET_GROUPID=%i\" % (os.getgid(),),\n                \"-e\",\n                \"DEB_BUILD_OPTIONS=%s\" % (\"nocheck\" if skip_tests else \"\"),\n                \"dh-venv-builder:\" + tag,\n            ],\n            stdout=stdout,\n            stderr=subprocess.STDOUT,\n        )\n\n        with self._lock:\n            self.active_containers.remove(container_name)\n\n        if stdout is not None:\n            stdout.close()\n            print(\"Completed build of %s\" % (dist,))\n\n    def kill_containers(self) -> None:\n        with self._lock:\n            active = list(self.active_containers)\n\n        for c in active:\n            print(\"killing container %s\" % (c,))\n            subprocess.run(\n                [\n                    \"docker\",\n                    \"kill\",\n                    c,\n                ],\n                stdout=subprocess.DEVNULL,\n            )\n            with self._lock:\n                self.active_containers.remove(c)\n\n\ndef run_builds(\n    builder: Builder, dists: Collection[str], jobs: int = 1, skip_tests: bool = False\n) -> None:\n    def sig(signum: int, _frame: Optional[FrameType]) -> None:\n        print(\"Caught SIGINT\")\n        builder.kill_containers()\n\n    signal.signal(signal.SIGINT, sig)\n\n    with ThreadPoolExecutor(max_workers=jobs) as e:\n        res = e.map(lambda dist: builder.run_build(dist, skip_tests), dists)\n\n    # make sure we consume the iterable so that exceptions are raised.\n    for _ in res:\n        pass\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=DESC,\n    )\n    parser.add_argument(\n        \"-j\",\n        \"--jobs\",\n        type=int,\n        default=1,\n        help=\"specify the number of builds to run in parallel\",\n    )\n    parser.add_argument(\n        \"--no-check\",\n        action=\"store_true\",\n        help=\"skip running tests after building\",\n    )\n    parser.add_argument(\n        \"--docker-build-arg\",\n        action=\"append\",\n        help=\"specify an argument to pass to docker build\",\n    )\n    parser.add_argument(\n        \"--show-dists-json\",\n        action=\"store_true\",\n        help=\"instead of building the packages, just list the dists to build for, as a json array\",\n    )\n    parser.add_argument(\n        \"dist\",\n        nargs=\"*\",\n        default=DISTS,\n        help=\"a list of distributions to build for. Default: %(default)s\",\n    )\n    args = parser.parse_args()\n    if args.show_dists_json:\n        print(json.dumps(DISTS))\n    else:\n        builder = Builder(\n            redirect_stdout=(args.jobs > 1), docker_build_args=args.docker_build_arg\n        )\n        run_builds(\n            builder,\n            dists=args.dist,\n            jobs=args.jobs,\n            skip_tests=args.no_check,\n        )\n", "path": "scripts-dev/build_debian_packages.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\n# Build the Debian packages using Docker images.\n#\n# This script builds the Docker images and then executes them sequentially, each\n# one building a Debian package for the targeted operating system. It is\n# designed to be a \"single command\" to produce all the images.\n#\n# By default, builds for all known distributions, but a list of distributions\n# can be passed on the commandline for debugging.\n\nimport argparse\nimport json\nimport os\nimport signal\nimport subprocess\nimport sys\nimport threading\nfrom concurrent.futures import ThreadPoolExecutor\nfrom types import FrameType\nfrom typing import Collection, Optional, Sequence, Set\n\nDISTS = (\n    \"debian:buster\",  # oldstable: EOL 2022-08\n    \"debian:bullseye\",\n    \"debian:bookworm\",\n    \"debian:sid\",\n    \"ubuntu:focal\",  # 20.04 LTS (our EOL forced by Py38 on 2024-10-14)\n    \"ubuntu:jammy\",  # 22.04 LTS (EOL 2027-04)\n)\n\nDESC = \"\"\"\\\nBuilds .debs for synapse, using a Docker image for the build environment.\n\nBy default, builds for all known distributions, but a list of distributions\ncan be passed on the commandline for debugging.\n\"\"\"\n\nprojdir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))\n\n\nclass Builder(object):\n    def __init__(\n        self,\n        redirect_stdout: bool = False,\n        docker_build_args: Optional[Sequence[str]] = None,\n    ):\n        self.redirect_stdout = redirect_stdout\n        self._docker_build_args = tuple(docker_build_args or ())\n        self.active_containers: Set[str] = set()\n        self._lock = threading.Lock()\n        self._failed = False\n\n    def run_build(self, dist: str, skip_tests: bool = False) -> None:\n        \"\"\"Build deb for a single distribution\"\"\"\n\n        if self._failed:\n            print(\"not building %s due to earlier failure\" % (dist,))\n            raise Exception(\"failed\")\n\n        try:\n            self._inner_build(dist, skip_tests)\n        except Exception as e:\n            print(\"build of %s failed: %s\" % (dist, e), file=sys.stderr)\n            self._failed = True\n            raise\n\n    def _inner_build(self, dist: str, skip_tests: bool = False) -> None:\n        tag = dist.split(\":\", 1)[1]\n\n        # Make the dir where the debs will live.\n        #\n        # Note that we deliberately put this outside the source tree, otherwise\n        # we tend to get source packages which are full of debs. (We could hack\n        # around that with more magic in the build_debian.sh script, but that\n        # doesn't solve the problem for natively-run dpkg-buildpakage).\n        debsdir = os.path.join(projdir, \"../debs\")\n        os.makedirs(debsdir, exist_ok=True)\n\n        if self.redirect_stdout:\n            logfile = os.path.join(debsdir, \"%s.buildlog\" % (tag,))\n            print(\"building %s: directing output to %s\" % (dist, logfile))\n            stdout = open(logfile, \"w\")\n        else:\n            stdout = None\n\n        # first build a docker image for the build environment\n        build_args = (\n            (\n                \"docker\",\n                \"build\",\n                \"--tag\",\n                \"dh-venv-builder:\" + tag,\n                \"--build-arg\",\n                \"distro=\" + dist,\n                \"-f\",\n                \"docker/Dockerfile-dhvirtualenv\",\n            )\n            + self._docker_build_args\n            + (\"docker\",)\n        )\n\n        subprocess.check_call(\n            build_args,\n            stdout=stdout,\n            stderr=subprocess.STDOUT,\n            cwd=projdir,\n        )\n\n        container_name = \"synapse_build_\" + tag\n        with self._lock:\n            self.active_containers.add(container_name)\n\n        # then run the build itself\n        subprocess.check_call(\n            [\n                \"docker\",\n                \"run\",\n                \"--rm\",\n                \"--name\",\n                container_name,\n                \"--volume=\" + projdir + \":/synapse/source:ro\",\n                \"--volume=\" + debsdir + \":/debs\",\n                \"-e\",\n                \"TARGET_USERID=%i\" % (os.getuid(),),\n                \"-e\",\n                \"TARGET_GROUPID=%i\" % (os.getgid(),),\n                \"-e\",\n                \"DEB_BUILD_OPTIONS=%s\" % (\"nocheck\" if skip_tests else \"\"),\n                \"dh-venv-builder:\" + tag,\n            ],\n            stdout=stdout,\n            stderr=subprocess.STDOUT,\n        )\n\n        with self._lock:\n            self.active_containers.remove(container_name)\n\n        if stdout is not None:\n            stdout.close()\n            print(\"Completed build of %s\" % (dist,))\n\n    def kill_containers(self) -> None:\n        with self._lock:\n            active = list(self.active_containers)\n\n        for c in active:\n            print(\"killing container %s\" % (c,))\n            subprocess.run(\n                [\n                    \"docker\",\n                    \"kill\",\n                    c,\n                ],\n                stdout=subprocess.DEVNULL,\n            )\n            with self._lock:\n                self.active_containers.remove(c)\n\n\ndef run_builds(\n    builder: Builder, dists: Collection[str], jobs: int = 1, skip_tests: bool = False\n) -> None:\n    def sig(signum: int, _frame: Optional[FrameType]) -> None:\n        print(\"Caught SIGINT\")\n        builder.kill_containers()\n\n    signal.signal(signal.SIGINT, sig)\n\n    with ThreadPoolExecutor(max_workers=jobs) as e:\n        res = e.map(lambda dist: builder.run_build(dist, skip_tests), dists)\n\n    # make sure we consume the iterable so that exceptions are raised.\n    for _ in res:\n        pass\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(\n        description=DESC,\n    )\n    parser.add_argument(\n        \"-j\",\n        \"--jobs\",\n        type=int,\n        default=1,\n        help=\"specify the number of builds to run in parallel\",\n    )\n    parser.add_argument(\n        \"--no-check\",\n        action=\"store_true\",\n        help=\"skip running tests after building\",\n    )\n    parser.add_argument(\n        \"--docker-build-arg\",\n        action=\"append\",\n        help=\"specify an argument to pass to docker build\",\n    )\n    parser.add_argument(\n        \"--show-dists-json\",\n        action=\"store_true\",\n        help=\"instead of building the packages, just list the dists to build for, as a json array\",\n    )\n    parser.add_argument(\n        \"dist\",\n        nargs=\"*\",\n        default=DISTS,\n        help=\"a list of distributions to build for. Default: %(default)s\",\n    )\n    args = parser.parse_args()\n    if args.show_dists_json:\n        print(json.dumps(DISTS))\n    else:\n        builder = Builder(\n            redirect_stdout=(args.jobs > 1), docker_build_args=args.docker_build_arg\n        )\n        run_builds(\n            builder,\n            dists=args.dist,\n            jobs=args.jobs,\n            skip_tests=args.no_check,\n        )\n", "path": "scripts-dev/build_debian_packages.py"}]}