-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Due diligence
Please try searching the issue tracker for your problem if you haven't already!
If you find related issues that aren't an exact match, feel free to continue
making a report, and link to those issues.
Describe the bug
A clear and concise description of what the bug is.
ThreadException (ConnectionResetError: [Errno 104]) when exiting a Connection.forward_local() context manager
To Reproduce
Steps to reproduce the behaviour (please attach a minimal example):
- Setup a connection in the following fashion:
connection = Connection(
host=hostname,
connect_kwargs={"pkey": pkey, "look_for_keys": False},
)
- Set up a context manager like so:
with connection.forward_local(local_port=10014, remote_port=9005):
- Inside of the context manager, interact with a browser using async Playwright. Create two pages, navigate through some locators.
- Close the Playwright pages, browser and async Playwright using the .close() and .stop() methods (verified using print and sleep that the error occurs after all has been closed)
- Have the context manager exit normally after leaving its indentation
Expected behaviour
The context manager exits gracefully and no ThreadException is raised.
Environment
Make sure your report gets the attention it deserves: bug reports with missing
information may be ignored or punted back to you, delaying a fix. The below
constitutes a bare minimum; more info is almost always better:
- What version of the Python interpreter are you using? Are you using an
alternative interpreter such as PyPy?
Python 3.11.9 through IPython 8.17.2 - What operating system are you using both client & server-side?
Client: AlmaLinux 9.5 (Teal Serval)
Server: Red Hat Enterprise Linux 9.5 (Plow) - Are you using OpenSSH server or something else?
Yes, OpenSSH_8.7p1 - Which version or versions of the software are you using?
fabric==3.2.2, paramiko==3.3.1- Have you already tried the latest release?
No - Have you, or can you, try some older releases to pin down where the bug
appeared?
I have not tried
- Have you already tried the latest release?
- How can the developers recreate the bug on their end? If possible, include a
copy of your code, the command you used to invoke it, and the full output of
your run (if applicable.)
File ~/repo_tool/system/tests/web_ui/file.py:458, in main()
455 LOCAL_FORWARDED_PORT = 10014
457 # .forward_local needs to be a context man.
--> 458 with connection.forward_local(local_port=LOCAL_FORWARDED_PORT, remote_port=9005):
459 webui = WebUI(
460 "user",
461 "password",
(...)
464 ignore_https=True,
465 )
466 await webui.start()
File /usr/lib64/python3.11/contextlib.py:144, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
142 if typ is None:
143 try:
--> 144 next(self.gen)
145 except StopIteration:
146 return False
File ~/repo_tool/repo_tool_venv/lib64/python3.11/site-packages/fabric/connection.py:1003, in Connection.forward_local(self, local_port, remote_port, remote_host, local_host)
1001 if wrapper is not None:
1002 if wrapper.type is ThreadException:
-> 1003 raise wrapper.value
1004 else:
1005 raise ThreadException([wrapper])
File ~/repo_tool/repo_tool_venv/lib64/python3.11/site-packages/invoke/util.py:209, in ExceptionHandlingThread.run(self)
188 try:
189 # Allow subclasses implemented using the "override run()'s body"
190 # approach to work, by using _run() instead of run(). If that
191 # doesn't appear to be the case, then assume we're being used
192 # directly and just use super() ourselves.
193 # XXX https://github.com/python/mypy/issues/1424
194 if hasattr(self, "_run") and callable(self._run): # type: ignore
195 # TODO: this could be:
196 # - io worker with no 'result' (always local)
(...)
207 # - assume the run/sudo/etc case will use a queue inside its
208 # worker body, orthogonal to how exception handling works
--> 209 self._run() # type: ignore
210 else:
211 super().run()
File ~/repo_tool/repo_tool_venv/lib64/python3.11/site-packages/fabric/tunnels.py:102, in TunnelManager._run(self)
100 # Handle exceptions
101 if exceptions:
--> 102 raise ThreadException(exceptions)
104 # All we have left to close is our own sock.
105 # TODO: use try/finally?
106 sock.close()
- A common tactic is to pare down your code until a simple (but still
bug-causing) “base case” remains. Not only can this help you identify
problems which aren’t real bugs, but it means the developer can get to fixing
the bug faster.
Additional context
Add any other context about the problem here.