Skip to content

Commit 89fd4a2

Browse files
authored
docs(fspy): document zero-initialized shared memory (#538)
## Motivation The shared-memory writer requires unused bytes to start at zero, but `fspy_shm` did not document that guarantee. Document the contract and add cross-platform regression coverage through owner and opened views so backend changes cannot silently violate it.
1 parent 56a73d6 commit 89fd4a2

5 files changed

Lines changed: 26 additions & 8 deletions

File tree

crates/fspy_shm/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The public API is defined in [`src/lib.rs`](src/lib.rs).
1010

1111
| API | Contract |
1212
| ----------------- | ---------------------------------------------------------------------------------- |
13-
| `create(size)` | Creates a non-empty mapping and returns its unique owner. |
13+
| `create(size)` | Creates a non-empty, zero-initialized mapping and returns its unique owner. |
1414
| `open(id)` | Opens another view of the mapping identified by `id`. |
1515
| `Shm::id()` | Returns the identifier to send to another process. |
1616
| `Shm::len()` | Returns the mapped size. |
@@ -19,6 +19,8 @@ The public API is defined in [`src/lib.rs`](src/lib.rs).
1919

2020
`Shm` does not synchronize memory access. The fspy channel combines it with atomic frame headers and a lock file. Senders hold a shared file lock while writing. The receiver takes the exclusive lock before reading, which waits for existing senders and rejects new ones.
2121

22+
Every byte in a mapping returned by `create` is initially zero. `open` exposes the mapping's current contents and does not reinitialize them.
23+
2224
## Ownership semantics
2325

2426
`create` returns the only owner. `open` returns non-owning views.

crates/fspy_shm/src/lib.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,23 @@ mod tests {
2222

2323
// Page-aligned on all supported targets.
2424
const SIZE: usize = 64 * 1024;
25+
// Use one byte more than 64 KiB to test multiple pages and a partial last page.
26+
const ZERO_INITIALIZED_SIZE: usize = SIZE + 1;
27+
28+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
29+
async fn new_mapping_is_zero_initialized_in_all_views() {
30+
let owner = create(ZERO_INITIALIZED_SIZE).unwrap();
31+
let opened = open(owner.id()).unwrap();
32+
33+
assert_zero_initialized(&owner);
34+
assert_zero_initialized(&opened);
35+
}
2536

2637
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
2738
async fn create_and_open_are_shared() {
2839
let owner = create(SIZE).unwrap();
2940
assert_eq!(owner.len(), SIZE);
3041
assert_eq!(owner.as_ptr() as usize % align_of::<usize>(), 0);
31-
// SAFETY: No writes occur while this slice is borrowed.
32-
assert!(unsafe { owner.as_slice() }.iter().all(|byte| *byte == 0));
3342

3443
let opened = open(owner.id()).unwrap();
3544
assert_eq!(opened.id(), owner.id());
@@ -90,6 +99,12 @@ mod tests {
9099
unsafe { shm.as_ptr().add(index).read() }
91100
}
92101

102+
fn assert_zero_initialized(shm: &Shm) {
103+
assert!(shm.len() >= ZERO_INITIALIZED_SIZE);
104+
// SAFETY: No writes occur while this slice is borrowed.
105+
assert!(unsafe { shm.as_slice() }.iter().all(|byte| *byte == 0));
106+
}
107+
93108
fn write_byte(shm: &Shm, index: usize, value: u8) {
94109
assert!(index < shm.len());
95110
// SAFETY: The index is in bounds and tests synchronize all accesses.

crates/fspy_shm/src/linux/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ pub struct Shm {
1717
_service: Option<DropGuard>,
1818
}
1919

20-
/// Creates a sealed memfd mapping of `size` bytes and returns its owner.
20+
/// Creates a zero-initialized sealed memfd mapping of `size` bytes and returns
21+
/// its owner.
2122
///
2223
/// The memfd is handed out to other processes by a broker task spawned onto
2324
/// the ambient tokio runtime. The broker stops on its own when the owner is

crates/fspy_shm/src/macos/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ pub struct Shm {
2424
owner: bool,
2525
}
2626

27-
/// Creates a POSIX shared-memory mapping of `size` bytes and returns its
28-
/// owner.
27+
/// Creates a zero-initialized POSIX shared-memory mapping of `size` bytes and
28+
/// returns its owner.
2929
///
3030
/// # Errors
3131
///

crates/fspy_shm/src/windows/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ pub struct Shm {
2424
backing_file: Option<File>,
2525
}
2626

27-
/// Creates a sparse, temporary file-backed named mapping of `size` bytes and
28-
/// returns its owner.
27+
/// Creates a zero-initialized, sparse, temporary file-backed named mapping of
28+
/// `size` bytes and returns its owner.
2929
///
3030
/// # Errors
3131
///

0 commit comments

Comments
 (0)