Skip to content

Commit 40b08a0

Browse files
committed
try to fix Python getting stuck during finalizer
See #63 for more details.
1 parent 99389dd commit 40b08a0

File tree

3 files changed

+46
-13
lines changed

3 files changed

+46
-13
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919

2020
matrix:
2121
os: [ubuntu-latest, macos-latest]
22-
pyv: ["3.8", "3.9", "3.10", "3.11.0-rc - 3.11", "3.12"]
22+
pyv: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
2323

2424
steps:
2525
- uses: actions/checkout@v4

setup.cfg

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ long_description_content_type = text/markdown
77
classifiers =
88
Development Status :: 4 - Beta
99
Programming Language :: Python :: 3
10-
Programming Language :: Python :: 3.7
1110
Programming Language :: Python :: 3.8
1211
Programming Language :: Python :: 3.9
1312
Programming Language :: Python :: 3.10
13+
Programming Language :: Python :: 3.11
14+
Programming Language :: Python :: 3.12
15+
Programming Language :: Python :: 3.13
16+
Programming Language :: Python :: 3.14
1417

1518
[options]
1619
install_requires =

sshfs/spec.py

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88

99
import asyncssh
1010
from asyncssh.sftp import SFTPOpUnsupported
11-
from fsspec.asyn import AsyncFileSystem, async_methods, sync, sync_wrapper
11+
from fsspec.asyn import (
12+
AsyncFileSystem,
13+
FSTimeoutError,
14+
async_methods,
15+
sync,
16+
sync_wrapper,
17+
)
1218
from fsspec.utils import infer_storage_options
1319

1420
from sshfs.file import SSHFile
@@ -71,7 +77,12 @@ def __init__(
7177
**_client_args,
7278
)
7379
weakref.finalize(
74-
self, sync, self.loop, self._finalize, self._pool, self._stack
80+
self,
81+
self._finalize,
82+
self.loop,
83+
self._client,
84+
self._pool,
85+
self._stack,
7586
)
7687

7788
@classmethod
@@ -101,15 +112,34 @@ async def _connect(
101112
connect = sync_wrapper(_connect)
102113

103114
@staticmethod
104-
async def _finalize(pool, stack):
105-
await pool.close()
106-
107-
# If an error occurs while the SSHFile is trying to
108-
# open the native file, then the client might get broken
109-
# due to partial initialization. We are just going to ignore
110-
# the errors that arises on the finalization layer
111-
with suppress(BrokenPipeError):
112-
await stack.aclose()
115+
def _finalize(loop, client, pool, stack):
116+
async def close():
117+
await pool.close()
118+
# If an error occurs while the SSHFile is trying to
119+
# open the native file, then the client might get broken
120+
# due to partial initialization. We are just going to ignore
121+
# the errors that arises on the finalization layer
122+
with suppress(BrokenPipeError):
123+
await stack.aclose()
124+
125+
if loop is not None and loop.is_running():
126+
try:
127+
loop = asyncio.get_running_loop()
128+
loop.create_task(close())
129+
return
130+
except RuntimeError:
131+
pass
132+
133+
try:
134+
sync(loop, close, timeout=0.1)
135+
return
136+
except FSTimeoutError:
137+
pass
138+
139+
try:
140+
client.abort() # try to abort the connection if no loop is running
141+
except Exception:
142+
pass
113143

114144
@property
115145
def client(self):

0 commit comments

Comments
 (0)