We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
The mitmproxy program failed to start because the default port 8080 was occupied.
#### Problem Description
Because the default port 8080 is occupied, the mitmproxy program fails to start, and there is no output reason for the failure.

#### Steps to reproduce the behavior:
1. Listen on port 8080 using the nc command in a terminal window.
2. Start the mitmproxy program in another terminal window.
3. The mitmproxy program failed to start, and there was no output reason for the failure, and the normal terminal configuration was not restored.
![image](https://github.com/mitmproxy/mitmproxy/assets/32811372/e8333100-fceb-4fdb-b781-829a9ce89945)



#### System Information
Mitmproxy: 10.2.3 binary
Python:    3.12.2
OpenSSL:   OpenSSL 3.2.1 30 Jan 2024
Platform:  macOS-14.2.1-arm64-arm-64bit


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mitmproxy/master.py`
Content:
```
1 import asyncio
2 import logging
3 
4 from . import ctx as mitmproxy_ctx
5 from .addons import termlog
6 from .proxy.mode_specs import ReverseMode
7 from .utils import asyncio_utils
8 from mitmproxy import addonmanager
9 from mitmproxy import command
10 from mitmproxy import eventsequence
11 from mitmproxy import hooks
12 from mitmproxy import http
13 from mitmproxy import log
14 from mitmproxy import options
15 
16 logger = logging.getLogger(__name__)
17 
18 
19 class Master:
20     """
21     The master handles mitmproxy's main event loop.
22     """
23 
24     event_loop: asyncio.AbstractEventLoop
25     _termlog_addon: termlog.TermLog | None = None
26 
27     def __init__(
28         self,
29         opts: options.Options,
30         event_loop: asyncio.AbstractEventLoop | None = None,
31         with_termlog: bool = False,
32     ):
33         self.options: options.Options = opts or options.Options()
34         self.commands = command.CommandManager(self)
35         self.addons = addonmanager.AddonManager(self)
36 
37         if with_termlog:
38             self._termlog_addon = termlog.TermLog()
39             self.addons.add(self._termlog_addon)
40 
41         self.log = log.Log(self)  # deprecated, do not use.
42         self._legacy_log_events = log.LegacyLogEvents(self)
43         self._legacy_log_events.install()
44 
45         # We expect an active event loop here already because some addons
46         # may want to spawn tasks during the initial configuration phase,
47         # which happens before run().
48         self.event_loop = event_loop or asyncio.get_running_loop()
49         self.should_exit = asyncio.Event()
50         mitmproxy_ctx.master = self
51         mitmproxy_ctx.log = self.log  # deprecated, do not use.
52         mitmproxy_ctx.options = self.options
53 
54     async def run(self) -> None:
55         with (
56             asyncio_utils.install_exception_handler(self._asyncio_exception_handler),
57             asyncio_utils.set_eager_task_factory(),
58         ):
59             self.should_exit.clear()
60 
61             if ec := self.addons.get("errorcheck"):
62                 await ec.shutdown_if_errored()
63             if ps := self.addons.get("proxyserver"):
64                 # This may block for some proxy modes, so we also monitor should_exit.
65                 await asyncio.wait(
66                     [
67                         asyncio.create_task(ps.setup_servers()),
68                         asyncio.create_task(self.should_exit.wait()),
69                     ],
70                     return_when=asyncio.FIRST_COMPLETED,
71                 )
72             await self.running()
73             if ec := self.addons.get("errorcheck"):
74                 await ec.shutdown_if_errored()
75                 ec.finish()
76             try:
77                 await self.should_exit.wait()
78             finally:
79                 # .wait might be cancelled (e.g. by sys.exit)
80                 await self.done()
81 
82     def shutdown(self):
83         """
84         Shut down the proxy. This method is thread-safe.
85         """
86         # We may add an exception argument here.
87         self.event_loop.call_soon_threadsafe(self.should_exit.set)
88 
89     async def running(self) -> None:
90         await self.addons.trigger_event(hooks.RunningHook())
91 
92     async def done(self) -> None:
93         await self.addons.trigger_event(hooks.DoneHook())
94         self._legacy_log_events.uninstall()
95         if self._termlog_addon is not None:
96             self._termlog_addon.uninstall()
97 
98     def _asyncio_exception_handler(self, loop, context) -> None:
99         try:
100             exc: Exception = context["exception"]
101         except KeyError:
102             logger.error(f"Unhandled asyncio error: {context}")
103         else:
104             if isinstance(exc, OSError) and exc.errno == 10038:
105                 return  # suppress https://bugs.python.org/issue43253
106             logger.error(
107                 "Unhandled error in task.",
108                 exc_info=(type(exc), exc, exc.__traceback__),
109             )
110 
111     async def load_flow(self, f):
112         """
113         Loads a flow
114         """
115 
116         if (
117             isinstance(f, http.HTTPFlow)
118             and len(self.options.mode) == 1
119             and self.options.mode[0].startswith("reverse:")
120         ):
121             # When we load flows in reverse proxy mode, we adjust the target host to
122             # the reverse proxy destination for all flows we load. This makes it very
123             # easy to replay saved flows against a different host.
124             # We may change this in the future so that clientplayback always replays to the first mode.
125             mode = ReverseMode.parse(self.options.mode[0])
126             assert isinstance(mode, ReverseMode)
127             f.request.host, f.request.port, *_ = mode.address
128             f.request.scheme = mode.scheme
129 
130         for e in eventsequence.iterate(f):
131             await self.addons.handle_lifecycle(e)
132
```

Path: `mitmproxy/addons/errorcheck.py`
Content:
```
1 import asyncio
2 import logging
3 import sys
4 
5 from mitmproxy import log
6 
7 
8 class ErrorCheck:
9     """Monitor startup for error log entries, and terminate immediately if there are some."""
10 
11     repeat_errors_on_stderr: bool
12     """
13     Repeat all errors on stderr before exiting.
14     This is useful for the console UI, which otherwise swallows all output.
15     """
16 
17     def __init__(self, repeat_errors_on_stderr: bool = False) -> None:
18         self.repeat_errors_on_stderr = repeat_errors_on_stderr
19 
20         self.logger = ErrorCheckHandler()
21         self.logger.install()
22 
23     def finish(self):
24         self.logger.uninstall()
25 
26     async def shutdown_if_errored(self):
27         # don't run immediately, wait for all logging tasks to finish.
28         await asyncio.sleep(0)
29         if self.logger.has_errored:
30             plural = "s" if len(self.logger.has_errored) > 1 else ""
31             if self.repeat_errors_on_stderr:
32                 msg = "\n".join(self.logger.format(r) for r in self.logger.has_errored)
33                 print(f"Error{plural} logged during startup:\n{msg}", file=sys.stderr)
34             else:
35                 print(
36                     f"Error{plural} logged during startup, exiting...", file=sys.stderr
37                 )
38 
39             sys.exit(1)
40 
41 
42 class ErrorCheckHandler(log.MitmLogHandler):
43     def __init__(self) -> None:
44         super().__init__(logging.ERROR)
45         self.has_errored: list[logging.LogRecord] = []
46 
47     def emit(self, record: logging.LogRecord) -> None:
48         self.has_errored.append(record)
49
```
--- 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/mitmproxy/addons/errorcheck.py b/mitmproxy/addons/errorcheck.py
--- a/mitmproxy/addons/errorcheck.py
+++ b/mitmproxy/addons/errorcheck.py
@@ -3,6 +3,8 @@
 import sys
 
 from mitmproxy import log
+from mitmproxy.contrib import click as miniclick
+from mitmproxy.utils import vt_codes
 
 
 class ErrorCheck:
@@ -29,8 +31,13 @@
         if self.logger.has_errored:
             plural = "s" if len(self.logger.has_errored) > 1 else ""
             if self.repeat_errors_on_stderr:
-                msg = "\n".join(self.logger.format(r) for r in self.logger.has_errored)
-                print(f"Error{plural} logged during startup:\n{msg}", file=sys.stderr)
+                message = f"Error{plural} logged during startup:"
+                if vt_codes.ensure_supported(sys.stderr):  # pragma: no cover
+                    message = miniclick.style(message, fg="red")
+                details = "\n".join(
+                    self.logger.format(r) for r in self.logger.has_errored
+                )
+                print(f"{message}\n{details}", file=sys.stderr)
             else:
                 print(
                     f"Error{plural} logged during startup, exiting...", file=sys.stderr
diff --git a/mitmproxy/master.py b/mitmproxy/master.py
--- a/mitmproxy/master.py
+++ b/mitmproxy/master.py
@@ -58,6 +58,7 @@
         ):
             self.should_exit.clear()
 
+            # Can we exit before even bringing up servers?
             if ec := self.addons.get("errorcheck"):
                 await ec.shutdown_if_errored()
             if ps := self.addons.get("proxyserver"):
@@ -69,14 +70,23 @@
                     ],
                     return_when=asyncio.FIRST_COMPLETED,
                 )
-            await self.running()
-            if ec := self.addons.get("errorcheck"):
-                await ec.shutdown_if_errored()
-                ec.finish()
+                if self.should_exit.is_set():
+                    return
+                # Did bringing up servers fail?
+                if ec := self.addons.get("errorcheck"):
+                    await ec.shutdown_if_errored()
+
             try:
+                await self.running()
+                # Any errors in the final part of startup?
+                if ec := self.addons.get("errorcheck"):
+                    await ec.shutdown_if_errored()
+                    ec.finish()
+
                 await self.should_exit.wait()
             finally:
-                # .wait might be cancelled (e.g. by sys.exit)
+                # if running() was called, we also always want to call done().
+                # .wait might be cancelled (e.g. by sys.exit), so  this needs to be in a finally block.
                 await self.done()
 
     def shutdown(self):

{"golden_diff": "diff --git a/mitmproxy/addons/errorcheck.py b/mitmproxy/addons/errorcheck.py\n--- a/mitmproxy/addons/errorcheck.py\n+++ b/mitmproxy/addons/errorcheck.py\n@@ -3,6 +3,8 @@\n import sys\n \n from mitmproxy import log\n+from mitmproxy.contrib import click as miniclick\n+from mitmproxy.utils import vt_codes\n \n \n class ErrorCheck:\n@@ -29,8 +31,13 @@\n         if self.logger.has_errored:\n             plural = \"s\" if len(self.logger.has_errored) > 1 else \"\"\n             if self.repeat_errors_on_stderr:\n-                msg = \"\\n\".join(self.logger.format(r) for r in self.logger.has_errored)\n-                print(f\"Error{plural} logged during startup:\\n{msg}\", file=sys.stderr)\n+                message = f\"Error{plural} logged during startup:\"\n+                if vt_codes.ensure_supported(sys.stderr):  # pragma: no cover\n+                    message = miniclick.style(message, fg=\"red\")\n+                details = \"\\n\".join(\n+                    self.logger.format(r) for r in self.logger.has_errored\n+                )\n+                print(f\"{message}\\n{details}\", file=sys.stderr)\n             else:\n                 print(\n                     f\"Error{plural} logged during startup, exiting...\", file=sys.stderr\ndiff --git a/mitmproxy/master.py b/mitmproxy/master.py\n--- a/mitmproxy/master.py\n+++ b/mitmproxy/master.py\n@@ -58,6 +58,7 @@\n         ):\n             self.should_exit.clear()\n \n+            # Can we exit before even bringing up servers?\n             if ec := self.addons.get(\"errorcheck\"):\n                 await ec.shutdown_if_errored()\n             if ps := self.addons.get(\"proxyserver\"):\n@@ -69,14 +70,23 @@\n                     ],\n                     return_when=asyncio.FIRST_COMPLETED,\n                 )\n-            await self.running()\n-            if ec := self.addons.get(\"errorcheck\"):\n-                await ec.shutdown_if_errored()\n-                ec.finish()\n+                if self.should_exit.is_set():\n+                    return\n+                # Did bringing up servers fail?\n+                if ec := self.addons.get(\"errorcheck\"):\n+                    await ec.shutdown_if_errored()\n+\n             try:\n+                await self.running()\n+                # Any errors in the final part of startup?\n+                if ec := self.addons.get(\"errorcheck\"):\n+                    await ec.shutdown_if_errored()\n+                    ec.finish()\n+\n                 await self.should_exit.wait()\n             finally:\n-                # .wait might be cancelled (e.g. by sys.exit)\n+                # if running() was called, we also always want to call done().\n+                # .wait might be cancelled (e.g. by sys.exit), so  this needs to be in a finally block.\n                 await self.done()\n \n     def shutdown(self):\n", "issue": "The mitmproxy program failed to start because the default port 8080 was occupied.\n#### Problem Description\r\nBecause the default port 8080 is occupied, the mitmproxy program fails to start, and there is no output reason for the failure.\r\n\r\n#### Steps to reproduce the behavior:\r\n1. Listen on port 8080 using the nc command in a terminal window.\r\n2. Start the mitmproxy program in another terminal window.\r\n3. The mitmproxy program failed to start, and there was no output reason for the failure, and the normal terminal configuration was not restored.\r\n![image](https://github.com/mitmproxy/mitmproxy/assets/32811372/e8333100-fceb-4fdb-b781-829a9ce89945)\r\n\r\n\r\n\r\n#### System Information\r\nMitmproxy: 10.2.3 binary\r\nPython:    3.12.2\r\nOpenSSL:   OpenSSL 3.2.1 30 Jan 2024\r\nPlatform:  macOS-14.2.1-arm64-arm-64bit\r\n\n", "before_files": [{"content": "import asyncio\nimport logging\n\nfrom . import ctx as mitmproxy_ctx\nfrom .addons import termlog\nfrom .proxy.mode_specs import ReverseMode\nfrom .utils import asyncio_utils\nfrom mitmproxy import addonmanager\nfrom mitmproxy import command\nfrom mitmproxy import eventsequence\nfrom mitmproxy import hooks\nfrom mitmproxy import http\nfrom mitmproxy import log\nfrom mitmproxy import options\n\nlogger = logging.getLogger(__name__)\n\n\nclass Master:\n    \"\"\"\n    The master handles mitmproxy's main event loop.\n    \"\"\"\n\n    event_loop: asyncio.AbstractEventLoop\n    _termlog_addon: termlog.TermLog | None = None\n\n    def __init__(\n        self,\n        opts: options.Options,\n        event_loop: asyncio.AbstractEventLoop | None = None,\n        with_termlog: bool = False,\n    ):\n        self.options: options.Options = opts or options.Options()\n        self.commands = command.CommandManager(self)\n        self.addons = addonmanager.AddonManager(self)\n\n        if with_termlog:\n            self._termlog_addon = termlog.TermLog()\n            self.addons.add(self._termlog_addon)\n\n        self.log = log.Log(self)  # deprecated, do not use.\n        self._legacy_log_events = log.LegacyLogEvents(self)\n        self._legacy_log_events.install()\n\n        # We expect an active event loop here already because some addons\n        # may want to spawn tasks during the initial configuration phase,\n        # which happens before run().\n        self.event_loop = event_loop or asyncio.get_running_loop()\n        self.should_exit = asyncio.Event()\n        mitmproxy_ctx.master = self\n        mitmproxy_ctx.log = self.log  # deprecated, do not use.\n        mitmproxy_ctx.options = self.options\n\n    async def run(self) -> None:\n        with (\n            asyncio_utils.install_exception_handler(self._asyncio_exception_handler),\n            asyncio_utils.set_eager_task_factory(),\n        ):\n            self.should_exit.clear()\n\n            if ec := self.addons.get(\"errorcheck\"):\n                await ec.shutdown_if_errored()\n            if ps := self.addons.get(\"proxyserver\"):\n                # This may block for some proxy modes, so we also monitor should_exit.\n                await asyncio.wait(\n                    [\n                        asyncio.create_task(ps.setup_servers()),\n                        asyncio.create_task(self.should_exit.wait()),\n                    ],\n                    return_when=asyncio.FIRST_COMPLETED,\n                )\n            await self.running()\n            if ec := self.addons.get(\"errorcheck\"):\n                await ec.shutdown_if_errored()\n                ec.finish()\n            try:\n                await self.should_exit.wait()\n            finally:\n                # .wait might be cancelled (e.g. by sys.exit)\n                await self.done()\n\n    def shutdown(self):\n        \"\"\"\n        Shut down the proxy. This method is thread-safe.\n        \"\"\"\n        # We may add an exception argument here.\n        self.event_loop.call_soon_threadsafe(self.should_exit.set)\n\n    async def running(self) -> None:\n        await self.addons.trigger_event(hooks.RunningHook())\n\n    async def done(self) -> None:\n        await self.addons.trigger_event(hooks.DoneHook())\n        self._legacy_log_events.uninstall()\n        if self._termlog_addon is not None:\n            self._termlog_addon.uninstall()\n\n    def _asyncio_exception_handler(self, loop, context) -> None:\n        try:\n            exc: Exception = context[\"exception\"]\n        except KeyError:\n            logger.error(f\"Unhandled asyncio error: {context}\")\n        else:\n            if isinstance(exc, OSError) and exc.errno == 10038:\n                return  # suppress https://bugs.python.org/issue43253\n            logger.error(\n                \"Unhandled error in task.\",\n                exc_info=(type(exc), exc, exc.__traceback__),\n            )\n\n    async def load_flow(self, f):\n        \"\"\"\n        Loads a flow\n        \"\"\"\n\n        if (\n            isinstance(f, http.HTTPFlow)\n            and len(self.options.mode) == 1\n            and self.options.mode[0].startswith(\"reverse:\")\n        ):\n            # When we load flows in reverse proxy mode, we adjust the target host to\n            # the reverse proxy destination for all flows we load. This makes it very\n            # easy to replay saved flows against a different host.\n            # We may change this in the future so that clientplayback always replays to the first mode.\n            mode = ReverseMode.parse(self.options.mode[0])\n            assert isinstance(mode, ReverseMode)\n            f.request.host, f.request.port, *_ = mode.address\n            f.request.scheme = mode.scheme\n\n        for e in eventsequence.iterate(f):\n            await self.addons.handle_lifecycle(e)\n", "path": "mitmproxy/master.py"}, {"content": "import asyncio\nimport logging\nimport sys\n\nfrom mitmproxy import log\n\n\nclass ErrorCheck:\n    \"\"\"Monitor startup for error log entries, and terminate immediately if there are some.\"\"\"\n\n    repeat_errors_on_stderr: bool\n    \"\"\"\n    Repeat all errors on stderr before exiting.\n    This is useful for the console UI, which otherwise swallows all output.\n    \"\"\"\n\n    def __init__(self, repeat_errors_on_stderr: bool = False) -> None:\n        self.repeat_errors_on_stderr = repeat_errors_on_stderr\n\n        self.logger = ErrorCheckHandler()\n        self.logger.install()\n\n    def finish(self):\n        self.logger.uninstall()\n\n    async def shutdown_if_errored(self):\n        # don't run immediately, wait for all logging tasks to finish.\n        await asyncio.sleep(0)\n        if self.logger.has_errored:\n            plural = \"s\" if len(self.logger.has_errored) > 1 else \"\"\n            if self.repeat_errors_on_stderr:\n                msg = \"\\n\".join(self.logger.format(r) for r in self.logger.has_errored)\n                print(f\"Error{plural} logged during startup:\\n{msg}\", file=sys.stderr)\n            else:\n                print(\n                    f\"Error{plural} logged during startup, exiting...\", file=sys.stderr\n                )\n\n            sys.exit(1)\n\n\nclass ErrorCheckHandler(log.MitmLogHandler):\n    def __init__(self) -> None:\n        super().__init__(logging.ERROR)\n        self.has_errored: list[logging.LogRecord] = []\n\n    def emit(self, record: logging.LogRecord) -> None:\n        self.has_errored.append(record)\n", "path": "mitmproxy/addons/errorcheck.py"}], "after_files": [{"content": "import asyncio\nimport logging\n\nfrom . import ctx as mitmproxy_ctx\nfrom .addons import termlog\nfrom .proxy.mode_specs import ReverseMode\nfrom .utils import asyncio_utils\nfrom mitmproxy import addonmanager\nfrom mitmproxy import command\nfrom mitmproxy import eventsequence\nfrom mitmproxy import hooks\nfrom mitmproxy import http\nfrom mitmproxy import log\nfrom mitmproxy import options\n\nlogger = logging.getLogger(__name__)\n\n\nclass Master:\n    \"\"\"\n    The master handles mitmproxy's main event loop.\n    \"\"\"\n\n    event_loop: asyncio.AbstractEventLoop\n    _termlog_addon: termlog.TermLog | None = None\n\n    def __init__(\n        self,\n        opts: options.Options,\n        event_loop: asyncio.AbstractEventLoop | None = None,\n        with_termlog: bool = False,\n    ):\n        self.options: options.Options = opts or options.Options()\n        self.commands = command.CommandManager(self)\n        self.addons = addonmanager.AddonManager(self)\n\n        if with_termlog:\n            self._termlog_addon = termlog.TermLog()\n            self.addons.add(self._termlog_addon)\n\n        self.log = log.Log(self)  # deprecated, do not use.\n        self._legacy_log_events = log.LegacyLogEvents(self)\n        self._legacy_log_events.install()\n\n        # We expect an active event loop here already because some addons\n        # may want to spawn tasks during the initial configuration phase,\n        # which happens before run().\n        self.event_loop = event_loop or asyncio.get_running_loop()\n        self.should_exit = asyncio.Event()\n        mitmproxy_ctx.master = self\n        mitmproxy_ctx.log = self.log  # deprecated, do not use.\n        mitmproxy_ctx.options = self.options\n\n    async def run(self) -> None:\n        with (\n            asyncio_utils.install_exception_handler(self._asyncio_exception_handler),\n            asyncio_utils.set_eager_task_factory(),\n        ):\n            self.should_exit.clear()\n\n            # Can we exit before even bringing up servers?\n            if ec := self.addons.get(\"errorcheck\"):\n                await ec.shutdown_if_errored()\n            if ps := self.addons.get(\"proxyserver\"):\n                # This may block for some proxy modes, so we also monitor should_exit.\n                await asyncio.wait(\n                    [\n                        asyncio.create_task(ps.setup_servers()),\n                        asyncio.create_task(self.should_exit.wait()),\n                    ],\n                    return_when=asyncio.FIRST_COMPLETED,\n                )\n                if self.should_exit.is_set():\n                    return\n                # Did bringing up servers fail?\n                if ec := self.addons.get(\"errorcheck\"):\n                    await ec.shutdown_if_errored()\n\n            try:\n                await self.running()\n                # Any errors in the final part of startup?\n                if ec := self.addons.get(\"errorcheck\"):\n                    await ec.shutdown_if_errored()\n                    ec.finish()\n\n                await self.should_exit.wait()\n            finally:\n                # if running() was called, we also always want to call done().\n                # .wait might be cancelled (e.g. by sys.exit), so  this needs to be in a finally block.\n                await self.done()\n\n    def shutdown(self):\n        \"\"\"\n        Shut down the proxy. This method is thread-safe.\n        \"\"\"\n        # We may add an exception argument here.\n        self.event_loop.call_soon_threadsafe(self.should_exit.set)\n\n    async def running(self) -> None:\n        await self.addons.trigger_event(hooks.RunningHook())\n\n    async def done(self) -> None:\n        await self.addons.trigger_event(hooks.DoneHook())\n        self._legacy_log_events.uninstall()\n        if self._termlog_addon is not None:\n            self._termlog_addon.uninstall()\n\n    def _asyncio_exception_handler(self, loop, context) -> None:\n        try:\n            exc: Exception = context[\"exception\"]\n        except KeyError:\n            logger.error(f\"Unhandled asyncio error: {context}\")\n        else:\n            if isinstance(exc, OSError) and exc.errno == 10038:\n                return  # suppress https://bugs.python.org/issue43253\n            logger.error(\n                \"Unhandled error in task.\",\n                exc_info=(type(exc), exc, exc.__traceback__),\n            )\n\n    async def load_flow(self, f):\n        \"\"\"\n        Loads a flow\n        \"\"\"\n\n        if (\n            isinstance(f, http.HTTPFlow)\n            and len(self.options.mode) == 1\n            and self.options.mode[0].startswith(\"reverse:\")\n        ):\n            # When we load flows in reverse proxy mode, we adjust the target host to\n            # the reverse proxy destination for all flows we load. This makes it very\n            # easy to replay saved flows against a different host.\n            # We may change this in the future so that clientplayback always replays to the first mode.\n            mode = ReverseMode.parse(self.options.mode[0])\n            assert isinstance(mode, ReverseMode)\n            f.request.host, f.request.port, *_ = mode.address\n            f.request.scheme = mode.scheme\n\n        for e in eventsequence.iterate(f):\n            await self.addons.handle_lifecycle(e)\n", "path": "mitmproxy/master.py"}, {"content": "import asyncio\nimport logging\nimport sys\n\nfrom mitmproxy import log\nfrom mitmproxy.contrib import click as miniclick\nfrom mitmproxy.utils import vt_codes\n\n\nclass ErrorCheck:\n    \"\"\"Monitor startup for error log entries, and terminate immediately if there are some.\"\"\"\n\n    repeat_errors_on_stderr: bool\n    \"\"\"\n    Repeat all errors on stderr before exiting.\n    This is useful for the console UI, which otherwise swallows all output.\n    \"\"\"\n\n    def __init__(self, repeat_errors_on_stderr: bool = False) -> None:\n        self.repeat_errors_on_stderr = repeat_errors_on_stderr\n\n        self.logger = ErrorCheckHandler()\n        self.logger.install()\n\n    def finish(self):\n        self.logger.uninstall()\n\n    async def shutdown_if_errored(self):\n        # don't run immediately, wait for all logging tasks to finish.\n        await asyncio.sleep(0)\n        if self.logger.has_errored:\n            plural = \"s\" if len(self.logger.has_errored) > 1 else \"\"\n            if self.repeat_errors_on_stderr:\n                message = f\"Error{plural} logged during startup:\"\n                if vt_codes.ensure_supported(sys.stderr):  # pragma: no cover\n                    message = miniclick.style(message, fg=\"red\")\n                details = \"\\n\".join(\n                    self.logger.format(r) for r in self.logger.has_errored\n                )\n                print(f\"{message}\\n{details}\", file=sys.stderr)\n            else:\n                print(\n                    f\"Error{plural} logged during startup, exiting...\", file=sys.stderr\n                )\n\n            sys.exit(1)\n\n\nclass ErrorCheckHandler(log.MitmLogHandler):\n    def __init__(self) -> None:\n        super().__init__(logging.ERROR)\n        self.has_errored: list[logging.LogRecord] = []\n\n    def emit(self, record: logging.LogRecord) -> None:\n        self.has_errored.append(record)\n", "path": "mitmproxy/addons/errorcheck.py"}]}