Skip to content

Commit 4476ca1

Browse files
zackeesclaude
andauthored
refactor(platform): phase 6 migrate daemon IPC lifecycle (#1334)
* refactor(platform): migrate daemon IPC lifecycle Closes #1312 * fix(platform): enforce owner-only macOS local endpoints post-bind Darwin does not support fchmod() on socket fds; interprocess maps the EINVAL from ListenerOptions::mode() to ErrorKind::Unsupported, so every macOS local-endpoint bind failed (Check macOS on #1334: 'bind local endpoint: Kind(Unsupported)'). Linux keeps the atomic pre-bind fchmod. On macOS, bind first and chmod the socket path to 0600 immediately after, failing closed if the chmod fails. Co-Authored-By: Claude <noreply@anthropic.com> * chore(ci): regenerate platform boundary inventory after macOS IPC fix The Darwin post-bind-chmod change moved the PermissionsExt import and usage lines in macos/ipc.rs and dropped the unused ListenerOptionsExt import; the committed inventory drifted accordingly. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 662569f commit 4476ca1

30 files changed

Lines changed: 753 additions & 260 deletions

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,12 @@ bincode = "1"
132132
# to the version running-process 4.3.0 re-exports so the wire types stay
133133
# compatible. See crates/fbuild-daemon/src/broker.
134134
prost = "0.14"
135-
# fbuild-daemon binds the running-process backend endpoint directly so the
136-
# broker can verify and route to versioned daemon processes.
135+
# fbuild-core's selected IPC implementations bind the private running-process
136+
# backend endpoint and construct the daemon TCP listener.
137137
interprocess = "2.4.2"
138+
socket2 = "0.6"
139+
# Windows owner-only endpoint descriptors use static UTF-16 SDDL.
140+
widestring = "1.2"
138141
rayon = "1"
139142
tracing-test = "0.2"
140143
# Terminal coloring for `fbuild build --shrink` reporting (FastLED/fbuild#493).

ci/enforce_platform_boundary.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@
6969
),
7070
}
7171
)
72+
AUTHORIZED_BOUNDARY_FINDINGS.update(
73+
{
74+
(
75+
"crates/fbuild-core/\x43argo.toml",
76+
"native_dependency",
77+
dependency,
78+
"ipc",
79+
"host_mechanic",
80+
)
81+
for dependency in ("interprocess", "socket2")
82+
}
83+
)
7284
LEDGER_KINDS = {
7385
"attr_cfg",
7486
"cfg_macro",
@@ -81,14 +93,8 @@
8193
# Pre-expansion rustc visits exactly one of these mutually exclusive cfg
8294
# bodies on any host, while the whole-tree scanner intentionally inventories
8395
# both. Keep this projection adjustment explicit and occurrence-specific.
84-
DYLINT_HOST_EXCLUSIVE_ADJUSTMENTS = collections.Counter(
85-
{
86-
(
87-
"crates/fbuild-daemon/src/broker/backend.rs",
88-
"native_import",
89-
"interprocess",
90-
): 1,
91-
}
96+
DYLINT_HOST_EXCLUSIVE_ADJUSTMENTS: collections.Counter[tuple[str, str, str]] = (
97+
collections.Counter()
9298
)
9399

94100

ci/platform_boundary_ledger.tsv

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,9 @@ crates/fbuild-cli/src/cli/usb_recovery.rs native_path windows_sys:: 2 process ho
1919
crates/fbuild-cli/src/cli/usb_recovery.rs native_path windows_sys:: 3 process host_mechanic
2020
crates/fbuild-config/src/bin/enrich_boards.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic
2121
crates/fbuild-config/src/bin/enrich_boards.rs attr_cfg #[cfg(windows)] 0 host host_mechanic
22-
crates/fbuild-daemon/Cargo.toml native_dependency interprocess 0 process host_mechanic
23-
crates/fbuild-daemon/src/broker/backend.rs attr_cfg #[cfg(unix)] 0 ipc host_mechanic
24-
crates/fbuild-daemon/src/broker/backend.rs attr_cfg #[cfg(windows)] 0 ipc host_mechanic
25-
crates/fbuild-daemon/src/broker/backend.rs native_path interprocess::local_socket 0 process host_mechanic
26-
crates/fbuild-daemon/src/broker/backend.rs native_path interprocess::local_socket 1 process host_mechanic
27-
crates/fbuild-daemon/src/broker/backend.rs native_path interprocess::local_socket 2 process host_mechanic
28-
crates/fbuild-daemon/src/broker/backend.rs native_path interprocess::local_socket 3 process host_mechanic
2922
crates/fbuild-daemon/src/handlers/emulator/tests_npm_cache.rs attr_cfg #[cfg(windows)] 0 host_executable host_artifact_policy
3023
crates/fbuild-daemon/src/handlers/emulator/tests_process.rs attr_cfg #[cfg(not(windows))] 0 host_executable host_artifact_policy
3124
crates/fbuild-daemon/src/handlers/emulator/tests_process.rs attr_cfg #[cfg(windows)] 0 host_executable host_artifact_policy
32-
crates/fbuild-daemon/src/main.rs attr_cfg #[cfg(not(windows))] 0 host host_mechanic
33-
crates/fbuild-daemon/src/main.rs attr_cfg #[cfg(windows)] 0 host host_mechanic
34-
crates/fbuild-daemon/src/main.rs attr_cfg #[cfg(windows)] 1 host host_mechanic
35-
crates/fbuild-daemon/src/main.rs attr_cfg #[cfg(windows)] 2 host host_mechanic
36-
crates/fbuild-daemon/src/main.rs attr_cfg #[cfg(windows)] 3 host host_mechanic
37-
crates/fbuild-daemon/src/main.rs native_path std::os::windows::io::AsRawSocket 0 process host_mechanic
3825
crates/fbuild-deploy/src/lpc.rs attr_cfg #[cfg(not(target_os=))] 0 device host_mechanic
3926
crates/fbuild-deploy/src/lpc.rs attr_cfg #[cfg(not(windows))] 0 device host_mechanic
4027
crates/fbuild-deploy/src/lpc.rs attr_cfg #[cfg(target_os=)] 0 device host_mechanic

ci/platform_boundary_research.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"mach2",
3838
"nix",
3939
"portable_pty",
40+
"socket2",
4041
"winapi",
4142
"windows",
4243
"windows_sys",
@@ -51,15 +52,15 @@
5152
r"\bstd\s*::\s*os\s*::\s*(?:windows|unix|linux|macos)\b"
5253
r"(?:\s*::\s*[A-Za-z_][A-Za-z0-9_]*)*"
5354
),
54-
re.compile(r"\b(?:windows_sys|winapi|libc|mach2|nix|portable_pty)\s*::"),
55+
re.compile(r"\b(?:windows_sys|winapi|libc|mach2|nix|portable_pty|socket2)\s*::"),
5556
re.compile(r"\bwindows\s*::\s*Win32\b"),
5657
re.compile(r"\binterprocess\s*::\s*os\s*::\s*(?:windows|unix)\b"),
5758
re.compile(r"\binterprocess\s*::\s*local_socket\b"),
5859
re.compile(r"\btokio\s*::\s*net\s*::\s*(?:windows|UnixListener|UnixStream)\b"),
5960
re.compile(r"\bwindows\s*::"),
6061
)
6162
SINGLE_NATIVE_USE = re.compile(
62-
r"\buse\s+(interprocess|libc|mach2|nix|portable_pty|winapi|windows|windows_sys)"
63+
r"\buse\s+(interprocess|libc|mach2|nix|portable_pty|socket2|winapi|windows|windows_sys)"
6364
r"\s*(?:as\s+[A-Za-z_][A-Za-z0-9_]*\s*)?;"
6465
)
6566
COMPILE_HOST_CONST = re.compile(r"\bstd\s*::\s*env\s*::\s*consts\s*::\s*(?:OS|ARCH)\b")
@@ -210,6 +211,8 @@ def enclosing_function(text: str, offset: int) -> str:
210211

211212
def classify(path: str, kind: str, normalized: str = "", context: str = "") -> tuple[str, str]:
212213
"""Assign the phase-1 owner class; phase 2 validates this per occurrence."""
214+
if path.startswith("crates/fbuild-core/src/platform/") and path.endswith("/ipc.rs"):
215+
return "ipc", "host_mechanic"
213216
if path == "crates/fbuild-core/\x43argo.toml":
214217
unix_table = "[target.'cfg(unix)'.dependencies]"
215218
windows_table = "[target.'cfg(windows)'.dependencies]"
@@ -220,6 +223,8 @@ def classify(path: str, kind: str, normalized: str = "", context: str = "") -> t
220223
("windows-sys", windows_table),
221224
}:
222225
return "fs", "host_mechanic"
226+
if kind == "native_dependency" and normalized in {"interprocess", "socket2"}:
227+
return "ipc", "host_mechanic"
223228
if kind in {"native_import", "native_path", "native_dependency"}:
224229
if normalized == "std::env::current_exe":
225230
return "host_executable", "host_mechanic"

ci/platform_boundary_research.tsv

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,38 @@ crates/fbuild-cli/src/cli/usb_recovery.rs 259 native_path windows_sys:: process
1919
crates/fbuild-cli/src/cli/usb_recovery.rs 262 native_path std::os::windows::ffi::OsStrExt process host_mechanic
2020
crates/fbuild-config/src/bin/enrich_boards.rs 74 attr_cfg #[cfg(windows)] host host_mechanic
2121
crates/fbuild-config/src/bin/enrich_boards.rs 78 attr_cfg #[cfg(not(windows))] host host_mechanic
22-
crates/fbuild-core/Cargo.toml 46 target_dependency_table [target.'cfg(unix)'.dependencies] fs host_mechanic
23-
crates/fbuild-core/Cargo.toml 48 native_dependency libc fs host_mechanic
24-
crates/fbuild-core/Cargo.toml 50 target_dependency_table [target.'cfg(windows)'.dependencies] fs host_mechanic
25-
crates/fbuild-core/Cargo.toml 53 native_dependency windows-sys fs host_mechanic
22+
crates/fbuild-core/Cargo.toml 47 native_dependency interprocess ipc host_mechanic
23+
crates/fbuild-core/Cargo.toml 48 native_dependency socket2 ipc host_mechanic
24+
crates/fbuild-core/Cargo.toml 50 target_dependency_table [target.'cfg(unix)'.dependencies] fs host_mechanic
25+
crates/fbuild-core/Cargo.toml 52 native_dependency libc fs host_mechanic
26+
crates/fbuild-core/Cargo.toml 54 target_dependency_table [target.'cfg(windows)'.dependencies] fs host_mechanic
27+
crates/fbuild-core/Cargo.toml 57 native_dependency windows-sys fs host_mechanic
2628
crates/fbuild-core/src/platform/executable.rs 56 native_path std::env::current_exe host_executable host_mechanic
2729
crates/fbuild-core/src/platform/linux/fs.rs 2 native_path std::os::unix::fs::PermissionsExt fs host_mechanic
2830
crates/fbuild-core/src/platform/linux/fs.rs 40 native_path std::os::unix::fs::symlink fs host_mechanic
2931
crates/fbuild-core/src/platform/linux/fs.rs 84 native_path std::os::unix::ffi::OsStrExt process host_mechanic
3032
crates/fbuild-core/src/platform/linux/fs.rs 89 native_path libc:: process host_mechanic
3133
crates/fbuild-core/src/platform/linux/fs.rs 91 native_path libc:: process host_mechanic
3234
crates/fbuild-core/src/platform/linux/fs.rs 101 native_path libc:: process host_mechanic
33-
crates/fbuild-core/src/platform/linux/mod.rs 9 compile_host_fact std::env::consts::ARCH host host_mechanic
35+
crates/fbuild-core/src/platform/linux/ipc.rs 1 native_path interprocess::local_socket ipc host_mechanic
36+
crates/fbuild-core/src/platform/linux/ipc.rs 2 native_path interprocess::local_socket ipc host_mechanic
37+
crates/fbuild-core/src/platform/linux/ipc.rs 3 native_path interprocess::os::unix ipc host_mechanic
38+
crates/fbuild-core/src/platform/linux/ipc.rs 4 native_path socket2:: ipc host_mechanic
39+
crates/fbuild-core/src/platform/linux/ipc.rs 66 native_path std::os::unix::fs::PermissionsExt ipc host_mechanic
40+
crates/fbuild-core/src/platform/linux/mod.rs 10 compile_host_fact std::env::consts::ARCH host host_mechanic
3441
crates/fbuild-core/src/platform/linux/process.rs 1 native_path std::os::unix::process::ExitStatusExt process host_mechanic
3542
crates/fbuild-core/src/platform/macos/fs.rs 2 native_path std::os::unix::fs::PermissionsExt fs host_mechanic
3643
crates/fbuild-core/src/platform/macos/fs.rs 40 native_path std::os::unix::fs::symlink fs host_mechanic
3744
crates/fbuild-core/src/platform/macos/fs.rs 84 native_path std::os::unix::ffi::OsStrExt process host_mechanic
3845
crates/fbuild-core/src/platform/macos/fs.rs 89 native_path libc:: process host_mechanic
3946
crates/fbuild-core/src/platform/macos/fs.rs 91 native_path libc:: process host_mechanic
4047
crates/fbuild-core/src/platform/macos/fs.rs 101 native_path libc:: process host_mechanic
41-
crates/fbuild-core/src/platform/macos/mod.rs 9 compile_host_fact std::env::consts::ARCH host host_mechanic
48+
crates/fbuild-core/src/platform/macos/ipc.rs 1 native_path interprocess::local_socket ipc host_mechanic
49+
crates/fbuild-core/src/platform/macos/ipc.rs 2 native_path interprocess::local_socket ipc host_mechanic
50+
crates/fbuild-core/src/platform/macos/ipc.rs 3 native_path socket2:: ipc host_mechanic
51+
crates/fbuild-core/src/platform/macos/ipc.rs 19 native_path std::os::unix::fs::PermissionsExt ipc host_mechanic
52+
crates/fbuild-core/src/platform/macos/ipc.rs 72 native_path std::os::unix::fs::PermissionsExt ipc host_mechanic
53+
crates/fbuild-core/src/platform/macos/mod.rs 10 compile_host_fact std::env::consts::ARCH host host_mechanic
4254
crates/fbuild-core/src/platform/macos/process.rs 1 native_path std::os::unix::process::ExitStatusExt process host_mechanic
4355
crates/fbuild-core/src/platform/windows/fs.rs 2 native_path std::os::windows::ffi::OsStrExt process host_mechanic
4456
crates/fbuild-core/src/platform/windows/fs.rs 3 native_path std::os::windows::fs fs host_mechanic
@@ -47,24 +59,17 @@ crates/fbuild-core/src/platform/windows/fs.rs 50 native_path std::os::windows::f
4759
crates/fbuild-core/src/platform/windows/fs.rs 78 native_path windows_sys:: process host_mechanic
4860
crates/fbuild-core/src/platform/windows/fs.rs 133 native_path windows_sys:: process host_mechanic
4961
crates/fbuild-core/src/platform/windows/fs.rs 177 native_path windows_sys:: process host_mechanic
50-
crates/fbuild-core/src/platform/windows/mod.rs 9 compile_host_fact std::env::consts::ARCH host host_mechanic
62+
crates/fbuild-core/src/platform/windows/ipc.rs 1 native_path interprocess::local_socket ipc host_mechanic
63+
crates/fbuild-core/src/platform/windows/ipc.rs 2 native_path interprocess::local_socket ipc host_mechanic
64+
crates/fbuild-core/src/platform/windows/ipc.rs 3 native_path interprocess::os::windows ipc host_mechanic
65+
crates/fbuild-core/src/platform/windows/ipc.rs 4 native_path interprocess::os::windows ipc host_mechanic
66+
crates/fbuild-core/src/platform/windows/ipc.rs 5 native_path socket2:: ipc host_mechanic
67+
crates/fbuild-core/src/platform/windows/ipc.rs 6 native_path std::os::windows::io::AsRawSocket ipc host_mechanic
68+
crates/fbuild-core/src/platform/windows/mod.rs 10 compile_host_fact std::env::consts::ARCH host host_mechanic
5169
crates/fbuild-core/src/platform/windows/process.rs 1 native_path std::os::windows::io::AsHandle process host_mechanic
52-
crates/fbuild-daemon/Cargo.toml 58 native_dependency interprocess process host_mechanic
53-
crates/fbuild-daemon/src/broker/backend.rs 11 native_path interprocess::local_socket process host_mechanic
54-
crates/fbuild-daemon/src/broker/backend.rs 188 native_path interprocess::local_socket process host_mechanic
55-
crates/fbuild-daemon/src/broker/backend.rs 189 attr_cfg #[cfg(unix)] ipc host_mechanic
56-
crates/fbuild-daemon/src/broker/backend.rs 195 native_path interprocess::local_socket process host_mechanic
57-
crates/fbuild-daemon/src/broker/backend.rs 200 attr_cfg #[cfg(windows)] ipc host_mechanic
58-
crates/fbuild-daemon/src/broker/backend.rs 202 native_path interprocess::local_socket process host_mechanic
5970
crates/fbuild-daemon/src/handlers/emulator/tests_npm_cache.rs 146 attr_cfg #[cfg(windows)] host_executable host_artifact_policy
6071
crates/fbuild-daemon/src/handlers/emulator/tests_process.rs 9 attr_cfg #[cfg(windows)] host_executable host_artifact_policy
6172
crates/fbuild-daemon/src/handlers/emulator/tests_process.rs 21 attr_cfg #[cfg(not(windows))] host_executable host_artifact_policy
62-
crates/fbuild-daemon/src/main.rs 319 attr_cfg #[cfg(windows)] host host_mechanic
63-
crates/fbuild-daemon/src/main.rs 646 attr_cfg #[cfg(windows)] host host_mechanic
64-
crates/fbuild-daemon/src/main.rs 652 attr_cfg #[cfg(not(windows))] host host_mechanic
65-
crates/fbuild-daemon/src/main.rs 729 attr_cfg #[cfg(windows)] host host_mechanic
66-
crates/fbuild-daemon/src/main.rs 731 native_path std::os::windows::io::AsRawSocket process host_mechanic
67-
crates/fbuild-daemon/src/main.rs 776 attr_cfg #[cfg(windows)] host host_mechanic
6873
crates/fbuild-deploy/src/lpc.rs 27 attr_cfg #[cfg(target_os=)] device host_mechanic
6974
crates/fbuild-deploy/src/lpc.rs 31 attr_cfg #[cfg(not(target_os=))] device host_mechanic
7075
crates/fbuild-deploy/src/lpc.rs 972 attr_cfg #[cfg(windows)] device host_mechanic

ci/test_enforce_platform_boundary.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def setUpClass(cls) -> None:
1414
cls.observed = boundary.rows_from_findings(boundary.research.inventory())
1515

1616
def test_committed_exact_occurrence_ledger_matches_whole_tree(self) -> None:
17-
self.assertEqual(len(self.expected), 107)
17+
self.assertEqual(len(self.expected), 94)
1818
self.assertFalse(boundary.validate_ledger(self.expected))
1919
self.assertFalse(boundary.compare(self.expected, self.observed))
2020

@@ -105,6 +105,23 @@ def test_rp2040_filesystem_mechanics_use_the_neutral_facade(self) -> None:
105105
for forbidden in ("AsRawHandle", "CancelSynchronousIo", ".raw_os_error()"):
106106
self.assertNotIn(forbidden, source)
107107

108+
def test_daemon_ipc_and_shutdown_use_neutral_facades(self) -> None:
109+
backend = (
110+
boundary.ROOT / "crates/fbuild-daemon/src/broker/backend.rs"
111+
).read_text(encoding="utf-8")
112+
main = (boundary.ROOT / "crates/fbuild-daemon/src/main.rs").read_text(
113+
encoding="utf-8"
114+
)
115+
116+
self.assertNotIn("interprocess", backend)
117+
for forbidden in (
118+
"socket2",
119+
"AsRawSocket",
120+
"SetConsoleCtrlHandler",
121+
"windows_console",
122+
):
123+
self.assertNotIn(forbidden, main)
124+
108125
def test_executable_spelling_does_not_bypass_the_executable_facade(self) -> None:
109126
host_selected_exe = re.compile(
110127
r"if\s+(?:fbuild_core|crate)::platform::host::is_windows\(\)"

ci/test_platform_boundary_research.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,28 @@ def test_core_native_dependency_ownership_requires_matching_target_table(self) -
131131
[("process", "host_mechanic"), ("fs", "host_mechanic")],
132132
)
133133

134+
def test_core_ipc_dependencies_have_exact_ownership(self) -> None:
135+
path = "crates/fbuild-core/\x43argo.toml"
136+
for dependency in ("interprocess", "socket2"):
137+
with self.subTest(dependency=dependency):
138+
self.assertEqual(
139+
platform_boundary_research.classify(
140+
path, "native_dependency", dependency, ""
141+
),
142+
("ipc", "host_mechanic"),
143+
)
144+
145+
def test_selected_ipc_implementation_has_exact_ownership(self) -> None:
146+
self.assertEqual(
147+
platform_boundary_research.classify(
148+
"crates/fbuild-core/src/platform/windows/ipc.rs",
149+
"native_path",
150+
"socket2::",
151+
"",
152+
),
153+
("ipc", "host_mechanic"),
154+
)
155+
134156
def test_mixed_qemu_permissions_are_migrated_but_context_stays_classified(self) -> None:
135157
path = platform_boundary_research.ROOT / "crates/fbuild-toolchain/src/toolchain/esp_qemu.rs"
136158
findings = platform_boundary_research.scan_rust(path, platform_boundary_research.ROOT)

crates/fbuild-core/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ fs2 = { workspace = true }
4242
# Stable cross-platform file identity handles; construction remains confined
4343
# to the selected filesystem implementation.
4444
same-file = { workspace = true }
45+
# Local endpoint transport and native TCP listener construction are confined
46+
# to the selected `platform::ipc` implementations.
47+
interprocess = { workspace = true }
48+
socket2 = { workspace = true }
4549

4650
[target.'cfg(unix)'.dependencies]
4751
# Selected Unix filesystem mechanics query the exact mount containing a path.
@@ -51,6 +55,8 @@ libc = { workspace = true }
5155
# Selected Windows filesystem mechanics: removable-volume facts and retiring
5256
# a kernel-blocked output handle after its watchdog expires.
5357
windows-sys = { version = "0.52", features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_IO"] }
58+
# Selected Windows IPC creates a protected owner-only pipe descriptor.
59+
widestring = { workspace = true }
5460

5561
[dev-dependencies]
5662
tempfile = { workspace = true }

crates/fbuild-core/src/platform/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,9 @@ link/reparse classification, volume facts, native error classification, shared
1717
destination opening, atomic replacement, and blocked-I/O retirement. Cache
1818
sizing, archive traversal, authorization, locking, diagnostics, and retry policy
1919
remain with their product owners.
20+
21+
`ipc` owns fbuild local-endpoint bind/connect/accept and peer facts, owner-only
22+
Unix endpoint creation, TCP listener socket policy, and endpoint readiness
23+
probing. Broker framing/routing, daemon retry/yield policy, and HTTP/protobuf
24+
compatibility remain with the daemon. Additional native shutdown notifications
25+
route through `process` into the daemon's neutral shutdown channel.

0 commit comments

Comments
 (0)