Skip to content

Commit 647b68e

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

3 files changed

Lines changed: 36 additions & 15 deletions

File tree

.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: 31 additions & 13 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
@@ -70,9 +76,7 @@ def __init__(
7076
max_sftp_channels=max_sessions - _SHELL_CHANNELS,
7177
**_client_args,
7278
)
73-
weakref.finalize(
74-
self, sync, self.loop, self._finalize, self._pool, self._stack
75-
)
79+
weakref.finalize(self, self._finalize, self.loop, self._pool, self._stack)
7680

7781
@classmethod
7882
def _strip_protocol(cls, path):
@@ -101,15 +105,29 @@ async def _connect(
101105
connect = sync_wrapper(_connect)
102106

103107
@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()
108+
def _finalize(loop, pool, stack):
109+
async def close():
110+
await pool.close()
111+
# If an error occurs while the SSHFile is trying to
112+
# open the native file, then the client might get broken
113+
# due to partial initialization. We are just going to ignore
114+
# the errors that arises on the finalization layer
115+
with suppress(BrokenPipeError):
116+
await stack.aclose()
117+
118+
if loop is not None and loop.is_running():
119+
try:
120+
loop = asyncio.get_running_loop()
121+
loop.create_task(close())
122+
return
123+
except RuntimeError:
124+
pass
125+
126+
try:
127+
sync(loop, close, timeout=0.1)
128+
return
129+
except FSTimeoutError:
130+
pass
113131

114132
@property
115133
def client(self):

0 commit comments

Comments
 (0)