Skip to content

Commit 5663135

Browse files
committed
Fix mount-tests readiness detection on Unix and add FUSE diagnostics
1 parent 8ef4904 commit 5663135

2 files changed

Lines changed: 41 additions & 7 deletions

File tree

.github/workflows/ci.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,29 @@ jobs:
199199
- name: Verify FUSE backend
200200
run: |
201201
python -c "
202+
import sys, os
202203
try:
203204
from fuse import FUSE
204205
print('fusepy: OK (FUSE class imported)')
205206
except EnvironmentError as e:
206207
print(f'fusepy: FUSE backend not found: {e}')
208+
sys.exit(0)
207209
except ImportError:
208210
print('fusepy: not installed')
211+
sys.exit(0)
212+
# Verify /dev/fuse accessible on Linux
213+
if sys.platform.startswith('linux'):
214+
if os.path.exists('/dev/fuse'):
215+
mode = oct(os.stat('/dev/fuse').st_mode)
216+
print(f'/dev/fuse exists, mode={mode}')
217+
try:
218+
fd = os.open('/dev/fuse', os.O_RDWR)
219+
os.close(fd)
220+
print('/dev/fuse: read-write access OK')
221+
except PermissionError as e:
222+
print(f'/dev/fuse: access denied: {e}')
223+
else:
224+
print('/dev/fuse: NOT FOUND')
209225
"
210226
continue-on-error: true
211227

tests/integration/conftest.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ def _mount(image, driver=None, extra_args=None, timeout=_MOUNT_TIMEOUT):
211211
),
212212
)
213213

214+
# Cache parent device ID for Unix mount detection (st_dev changes
215+
# when FUSE attaches).
216+
if not sys.platform.startswith("win"):
217+
parent_dev = os.stat(os.path.dirname(str(mountpoint))).st_dev
218+
214219
# Poll until mount is detected or timeout
215220
deadline = time.monotonic() + timeout
216221
mounted = False
@@ -223,24 +228,37 @@ def _mount(image, driver=None, extra_args=None, timeout=_MOUNT_TIMEOUT):
223228
f"Mount process exited early (rc={proc.returncode}).\n"
224229
f"stdout: {stdout}\nstderr: {stderr}"
225230
)
226-
# On Windows, ismount detects the drive letter before the
227-
# filesystem is fully initialized. Use listdir as the
228-
# authoritative readiness check on all platforms.
231+
# Platform-aware readiness detection:
232+
# - Windows: drive letter doesn't exist until WinFSP creates it,
233+
# so listdir not throwing means the mount appeared.
234+
# - Unix: mountpoint directory already exists, so listdir would
235+
# succeed immediately. Instead check st_dev -- FUSE attaches a
236+
# new device, so st_dev will differ from the parent directory.
229237
try:
230-
os.listdir(str(mountpoint))
238+
if sys.platform.startswith("win"):
239+
os.listdir(str(mountpoint))
240+
else:
241+
if os.stat(str(mountpoint)).st_dev != parent_dev:
242+
mounted = True
243+
break
244+
else:
245+
time.sleep(_MOUNT_POLL_INTERVAL)
246+
continue
231247
mounted = True
232248
break
233249
except OSError:
234250
pass
235251
time.sleep(_MOUNT_POLL_INTERVAL)
236252

237253
if not mounted:
238-
# Clean up the failed mount attempt
254+
# Clean up the failed mount attempt and capture diagnostics
239255
proc.kill()
240256
proc.wait(timeout=_PROCESS_KILL_TIMEOUT)
257+
stdout = proc.stdout.read().decode(errors="replace")
258+
stderr = proc.stderr.read().decode(errors="replace")
241259
raise RuntimeError(
242-
f"Mount not detected at {mountpoint} within {timeout}s. "
243-
f"Process still running: {proc.poll() is None}"
260+
f"Mount not detected at {mountpoint} within {timeout}s.\n"
261+
f"stdout: {stdout}\nstderr: {stderr}"
244262
)
245263

246264
_active_mounts.append((proc, mountpoint))

0 commit comments

Comments
 (0)