Commit 29fcbd6
fix(fspy): unify shared memory on a sparse temp file across all platforms (#576)
## Motivation
Codex CLI's and Claude Code's default sandboxes deny the primitives
fspy's Unix shared memory was built on. The macOS Seatbelt profile
denies `shm_open` (#563), and both sandboxes block Unix domain sockets,
which the Linux memfd broker depended on. Plain files in the temp
directory work under both sandboxes; the IPC lock file lives there
today.
This PR replaces all three platform backends with one file-backed
implementation, mapped through `memmap2` on every platform. The API has
three types, each one platform concept:
- `ShmKeeper` is the name. `create` returns it, it carries the
identifier (the backing file's absolute path), and dropping it removes
the file with `remove_file`.
- `ShmHandle` is the opened file. `create` returns one, so the creator
never looks its own file up by name, and `open` returns one to everybody
else. `map` can be called more than once.
- `Mapping` is the bytes. It keeps them alive until dropped and cannot
affect the name.
Removal works on every platform because modern Windows deletes with
POSIX semantics: the name goes away at once, [existing handles keep
working](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_file_disposition_information_ex),
and [mapped views keep the data
alive](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-createfilemappingw).
CI probes on Windows Server confirmed both, with a live writable view
and with an open share-delete handle. The docs reserve the right to fail
the delete while a view is mapped, and Windows versions without POSIX
delete do fail it, so the keeper falls back to reopening the file with
`FILE_FLAG_DELETE_ON_CLOSE` and closing it. Unit tests pin the full
removal semantics: name gone with a live mapping, name gone with an open
handle, and the handle still mapping the same bytes afterwards.
Name removal is cleanup. The channel invalidates contents inside the
shared bytes, so nothing depends on removal timing. Backing files sit
directly in the system temp directory as `vite-task-fspy-<uuid>.shm`
with mode `0o600`; a shared subdirectory would belong to whichever user
created it first and lock everyone else out. The identifier is resolved
to an absolute path at creation, so a relative `TMPDIR` in the creating
process cannot mislead an opener with a different working directory.
There is no broker, no global object name, no tokio requirement, and no
hand-written mapping code: the Windows-specific parts shrink to the
sparse-file `FSCTL` and the creation flags.
If the keeper's process is killed, the file stays behind: on Unix for
the temp reaper, on Windows until a cleanup tool runs. It costs about as
much disk as the run wrote into it.
Refs #563.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 38a7569 commit 29fcbd6
17 files changed
Lines changed: 568 additions & 1208 deletions
File tree
- crates
- fspy_shm
- src
- file_backed
- linux
- macos
- windows
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
96 | | - | |
97 | 96 | | |
98 | 97 | | |
99 | 98 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
| 5 | + | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
| 12 | + | |
18 | 13 | | |
19 | 14 | | |
20 | 15 | | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | 16 | | |
49 | 17 | | |
50 | 18 | | |
51 | 19 | | |
52 | | - | |
53 | | - | |
| 20 | + | |
54 | 21 | | |
55 | 22 | | |
56 | 23 | | |
| |||
59 | 26 | | |
60 | 27 | | |
61 | 28 | | |
62 | | - | |
| 29 | + | |
| 30 | + | |
63 | 31 | | |
64 | | - | |
65 | | - | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
66 | 36 | | |
67 | | - | |
| 37 | + | |
68 | 38 | | |
69 | 39 | | |
70 | 40 | | |
| |||
80 | 50 | | |
81 | 51 | | |
82 | 52 | | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
87 | 58 | | |
88 | 59 | | |
89 | 60 | | |
90 | 61 | | |
91 | 62 | | |
92 | | - | |
| 63 | + | |
93 | 64 | | |
94 | 65 | | |
95 | 66 | | |
| |||
104 | 75 | | |
105 | 76 | | |
106 | 77 | | |
107 | | - | |
| 78 | + | |
108 | 79 | | |
109 | 80 | | |
110 | 81 | | |
111 | 82 | | |
112 | 83 | | |
113 | 84 | | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
121 | 85 | | |
122 | 86 | | |
123 | 87 | | |
| |||
129 | 93 | | |
130 | 94 | | |
131 | 95 | | |
132 | | - | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
133 | 99 | | |
134 | 100 | | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | 101 | | |
143 | 102 | | |
144 | 103 | | |
| |||
154 | 113 | | |
155 | 114 | | |
156 | 115 | | |
157 | | - | |
| 116 | + | |
158 | 117 | | |
159 | | - | |
| 118 | + | |
160 | 119 | | |
161 | 120 | | |
162 | 121 | | |
| |||
170 | 129 | | |
171 | 130 | | |
172 | 131 | | |
173 | | - | |
| 132 | + | |
174 | 133 | | |
175 | 134 | | |
176 | 135 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| |||
672 | 672 | | |
673 | 673 | | |
674 | 674 | | |
675 | | - | |
676 | | - | |
677 | | - | |
678 | | - | |
679 | | - | |
680 | | - | |
681 | | - | |
682 | | - | |
683 | | - | |
684 | | - | |
685 | | - | |
686 | | - | |
687 | | - | |
688 | | - | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
689 | 681 | | |
690 | 682 | | |
691 | 683 | | |
692 | 684 | | |
693 | 685 | | |
694 | 686 | | |
695 | | - | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
700 | 693 | | |
701 | 694 | | |
702 | 695 | | |
| |||
714 | 707 | | |
715 | 708 | | |
716 | 709 | | |
717 | | - | |
| 710 | + | |
718 | 711 | | |
719 | 712 | | |
720 | 713 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | 12 | | |
25 | 13 | | |
26 | 14 | | |
27 | | - | |
28 | 15 | | |
29 | 16 | | |
30 | | - | |
31 | 17 | | |
32 | 18 | | |
33 | 19 | | |
34 | | - | |
35 | 20 | | |
36 | 21 | | |
37 | 22 | | |
38 | 23 | | |
39 | 24 | | |
40 | | - | |
41 | 25 | | |
42 | 26 | | |
43 | 27 | | |
| |||
0 commit comments