Skip to content

Windows CI、per-fd 定位 IO 锁与沙箱门面保真 - #11

Merged
HeDaas-Code merged 5 commits into
masterfrom
dev/hardening
Sep 29, 2026
Merged

HeDaas-Code merged 5 commits into
masterfrom
dev/hardening

Conversation

@HeDaas-Code

Copy link
Copy Markdown
Owner

三件事,各自独立成提交,分别关闭一个跟进 issue:

验证:本地 452 passed(449 + 2 个 per-fd 测试 + 1 个沙箱拒绝测试)、pylint -E 0 error。

Closes #7, closes #8, closes #9。

PyVDisk Team added 5 commits September 30, 2026 01:45
…t job (#7)

PR #5 and the compat layer were validated on a real Windows machine exactly
once, by hand.  Every platform primitive the package touches lives in
pyvdisk/compat.py, and the emulation tests force those paths on Linux -- but
only a real Windows runner exercises msvcrt.locking, the directory-fsync
no-op and drive-letter handling against the actual OS.  GitHub-hosted
windows-latest runners are free for public repos, so:

- no-dependencies gains an os matrix (ubuntu-latest, windows-latest): the
  zero-dependency promise, the full stdlib-only suite and a quickstart
  smoke now hold on both platforms;
- Lint gains errors-windows: pylint -E resolves imports against the running
  interpreter, so an unguarded `import fcntl` -- the exact bug that made
  PR #5 necessary -- is an import-error on Windows, not a runtime surprise.

The hnswlib tests job stays Linux-only: the accelerator has no Windows
wheels and building it on the runner adds flake for no extra coverage of
compat.
…ss (#8)

PR #5's disk.py locked emulated positional IO per fd; the compat layer
collapsed that into a single module-level RLock, which on Windows serialises
block IO across *every* open DataDisk -- disk A's writes queue disk B's.  The
docstring's 'not a global lock' claim did not survive the refactor it was
written for.

Restore the per-descriptor design from the PR: _PIO_LOCKS maps fd -> RLock,
created on demand behind a tiny guard.  Entries are not pruned -- a reused fd
number shares its predecessor's lock, which can only add contention, never
incorrectness, and pruning would need a close hook this layer does not own.

Two tests pin the behaviour: same fd reuses one lock and different fds never
share one, and IO on descriptor b completes while descriptor a's lock is held
-- the exact scenario the global lock froze.
_SandboxFS wrapped move/copy/link/symlink/readlink/truncate/chmod/chown/
utime, but the capability-scoped view underneath implements none of them:
the wrappers could only ever die with a bare AttributeError.  The VScript
stdlib advertises the full disk's fs API, so an agent script that reached
for one of these verbs got an error that read like a sandbox bug, giving
the model nothing to correct with.

Drop the dead wrappers and make __getattr__ refuse anything the scoped
view does not implement with the carried-verb list instead -- which also
keeps future scoped verbs from leaking into the sandbox door unreviewed.
Path-less diagnostics (df, fsck, statfs) still pass straight through, and
stat() now forwards follow=, which stdlib fs_chmod/fs_chown rely on.

The new test drives the refusal through run_script for symlink/chmod/
truncate and asserts the message names the verbs that do exist.
The new errors-windows job earned its keep on the first push: on Windows,
pylint's os brain has no pread/pwrite/getuid/getgid to infer from, so the
guarded POSIX branches in compat (and the uid/gid assertions) read as E1101.
Disable no-member on exactly those four lines, each with a comment naming
the guard -- a bare module-level disable would also hide real no-member
bugs on os elsewhere.
Found by the new no-dependencies (windows-latest) job, first real-Windows
run of the sandbox suite: str(tmp_path) carries backslashes, and the
VScript lexer correctly rejects '\U' inside a plain string -- so the test
failed with a LexError before it ever reached the disk.  Same rule PR #5
taught the host tests; the policy layer takes the mixed separators fine.
On Linux as_posix() is a no-op, which is why CI never saw it.

Windows suite now stands at 445 passed / 6 skipped, one failure gone.
@HeDaas-Code
HeDaas-Code merged commit 1ca863f into master Sep 29, 2026
16 checks passed
@HeDaas-Code
HeDaas-Code deleted the dev/hardening branch September 30, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant