You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apple's open-source launchd hasn't moved since 2014 (launchd-842.92.1).
Both freebsd-launchd's minimal rewrite and ravynOS's near-full launchd
descend from this same source. Phase 5 imports it verbatim and layers
patches on top, matching how configd is already imported in
freebsd-launchd and how libdispatch is patched in gershwin-developer.
Why this over a ravynOS fork: clean provenance (every commit is either
Apple verbatim or our patch), license clarity, no inheritance of
NextBSD's 36 dormant #if 0/FIXME bisect markers, consistent with our
configd / libdispatch / libxpc import pattern, easy re-imports if
Apple ever publishes a newer launchd.
Estimated patch size: ~700-1500 lines on top of ~16,500 lines of clean
Apple source. Patches cover: bsd.prog.mk Makefile, MIG .defs build
orchestration, Mach API compat shims for our libmach subset,
<Availability.h> macros, audit-session workaround, per-user env file.
Also updated cross-references: the bootstrap-server risk discussion now
explains the Phase 3 (small standalone) vs Phase 5 (full Apple launchd)
split; the table-level summary points to the new Phase 5 approach.
Copy file name to clipboardExpand all lines: freebsd-libxpc-plan.html
+73-12Lines changed: 73 additions & 12 deletions
Original file line number
Diff line number
Diff line change
@@ -479,7 +479,12 @@ <h3>launchd</h3>
479
479
480
480
<p><strong>Critical missing pieces from <code>freebsd-launchd</code>:</strong> EnvironmentVariables, StartCalendarInterval, WorkingDirectory, UserName/GroupName, StandardOut/ErrorPath, Umask, ThrottleInterval, <code>launchctl load -w</code>, enable/disable, override-file mechanism. Per <ahref="freebsd-launchd-plan.html"><code>freebsd-launchd-plan</code></a>'s matrix — Phase 5 batch is the remaining work.</p>
481
481
482
-
<p><strong>Decision-critical:</strong> The NextBSD/ravynOS launchd is closer to Apple parity but only runs on a Mach-coupled kernel. Now that our <code>mach.ko</code> exists, we could theoretically <em>swap forward</em> — replace <code>freebsd-launchd</code>'s daemon with NextBSD/ravynOS's launchd source built against our libmach + libxpc. The cost is wiring all the missing Mach port traps (see <ahref="#deps">§6</a>) and getting the bootstrap server alive. The benefit is jumping from 1,500 LoC of hand-coded subset to 16k LoC of battle-tested Apple-shape code. <strong>This swap is enabled by libxpc.</strong></p>
482
+
<p><strong>Decision-critical:</strong> The NextBSD/ravynOS launchd is closer to Apple parity but only runs on a Mach-coupled kernel. Now that our <code>mach.ko</code> exists, we have two ways to swap forward to the Apple-shape launchd:</p>
<li><strong>Clean import from Apple <code>launchd-842.92.1</code></strong> — same source code as the ravynOS path (everyone descends from this), but with clean provenance, our own patch series, and no inherited cruft. Same model as our configd / libdispatch / libxpc imports. <strong>Chosen approach</strong> — see Phase 5 below.</li>
486
+
</ul>
487
+
<p>Either way, the swap is enabled by libxpc and jumps us from 1,500 LoC of hand-coded subset to 16k+ LoC of battle-tested Apple-shape code.</p>
483
488
484
489
<h3>configd / SystemConfiguration</h3>
485
490
@@ -695,7 +700,7 @@ <h3>Decision summary</h3>
695
700
<tr><td>libdispatch</td><td><spanclass="pill pill-good">pure C + blocks</span></td><td>gershwin-developer install</td></tr>
696
701
<tr><td>libnv (bundled with libxpc)</td><td><spanclass="pill pill-good">pure C</span></td><td>BSD libnv, bundled in libxpc tree</td></tr>
<tr><td>configd's small ObjC shim</td><td><spanclass="pill pill-good">GNUstep libobjc2</span></td><td><code>NCDaemon.m</code> already uses GNUstep runtime</td></tr>
701
706
<tr><td>SystemConfiguration framework</td><td><spanclass="pill pill-warn">C + CoreFoundation</span></td><td>Apple verbatim — same CF dependency as configd</td></tr>
@@ -813,7 +818,7 @@ <h3>libs-corebase coverage of configd's CF needs</h3>
813
818
<p><spanclass="verdict verdict-warn">Significant gaps — hybrid with Apple CF-Lite required.</span> Per the audit in §9.5: corebase has CFMachPort absent, CFRunLoop version1 sources unimplemented (TODO stub), CFPreferences absent. Roughly 3,000-5,000 lines of new/imported code needed — pulled from Apple's open-source CF-Lite (plain C, not ObjC). This is its own sub-project, sequenced before Phase 6 (configd functional).</p>
814
819
815
820
<h3>Bootstrap server complexity</h3>
816
-
<p><spanclass="verdict verdict-warn">Real work.</span><code>bootstrap_check_in</code> / <code>bootstrap_look_up</code> need a userspace name service. NextBSD/ravynOS have a working bootstrap server inside their launchd, but they're disabled in our cut-down <code>freebsd-launchd</code>. Bringing the bootstrap server up means partially or fully swapping <code>freebsd-launchd</code> for the NextBSD/ravynOS launchd source built against our libmach. This is the most significant scope change implied by libxpc.</p>
821
+
<p><spanclass="verdict verdict-warn">Real work.</span><code>bootstrap_check_in</code> / <code>bootstrap_look_up</code> need a userspace name service. Apple's launchd <em>is</em> the bootstrap server — the bootstrap subsystem is internal to the launchd daemon. Our current <code>freebsd-launchd</code> minimal rewrite doesn't have it; the clean Apple <code>launchd-842.92.1</code>import in Phase 5 will. Either we stand up a small standalone bootstrap server in Phase 3 (smaller, faster, gets libxpc tested), or we wait for Phase 5's full Apple launchd to bring the bootstrap server along with it. The plan recommends both: Phase 3 minimal standalone for testing, Phase 5 swap to Apple's full launchd for production.</p>
817
822
818
823
<h3>"Should we just use D-Bus or AF_UNIX everywhere?"</h3>
819
824
<p><spanclass="verdict verdict-no">Already decided: no.</span> The whole project's premise is that Apple's system-service plumbing — including XPC's connection-based-async-with-typed-dictionaries shape — is what we want to modernize FreeBSD <em>toward</em>. Substituting another IPC mechanism breaks source compatibility with every daemon we want to inherit. The cost of libxpc is the price of admission.</p>
<p>The hard part. Options, in order of effort:</p>
1000
1005
<ol>
1001
1006
<li><strong>Option A: minimal standalone bootstrap server.</strong> Write a tiny daemon that owns the bootstrap port, accepts <code>bootstrap_register</code> / <code>bootstrap_look_up</code> over Mach, stores port-name mappings in memory. ~500-1000 lines. Reuses NextBSD's MIG <code>.defs</code> for the bootstrap protocol.</li>
1002
-
<li><strong>Option B: port NextBSD/ravynOS launchd's bootstrap subsystem</strong>piecemeal — just<code>job_mig_dispatch</code> + the bootstrap port handling, not the rest of launchd. Maybe 2000-3000 lines. Closer to Apple-shape but heavier.</li>
1003
-
<li><strong>Option C: full launchd swap.</strong>Replace <code>freebsd-launchd</code>'s daemon entirely with NextBSD/ravynOS launchd source built against our libmach + libxpc. Highest payoff (16k LoC of working Apple-shape code), highest risk (most surface to debug). Defer to Phase 5.</li>
1007
+
<li><strong>Option B: extract just the bootstrap subsystem from Apple's launchd</strong> — pull<code>job_mig_dispatch</code> + bootstrap port handling out of <code>launchd-842.92.1</code> source, ship it as a standalone daemon. Maybe 2000-3000 lines. Closer to Apple-shape but heavier.</li>
1008
+
<li><strong>Option C: full clean Apple launchd import.</strong>Phase 5's plan: import <code>launchd-842.92.1</code> verbatim from <code>apple-oss-distributions/launchd</code>, build against our libmach + libxpc + libdispatch with a patch series for FreeBSD adaptations. Highest payoff (16k+ LoC of upstream-clean Apple code), highest risk (most surface to debug). This becomes the production launchd.</li>
1004
1009
</ol>
1005
-
<p>Recommended Phase 3 scope: <strong>Option A</strong>. Smallest critical path to "libxpc connections actually work end-to-end." Defer the larger launchd swap to Phase 5 once libxpc is proven.</p>
1010
+
<p>Recommended Phase 3 scope: <strong>Option A</strong>. Smallest critical path to "libxpc connections actually work end-to-end." The full Apple-launchd import comes in Phase 5 once libxpc is proven.</p>
1006
1011
1007
1012
<h3>Phase 4 — xpc_connection end-to-end test (1 week)</h3>
<li>This is the libxpc equivalent of C3's "userland mach_msg works end-to-end" milestone.</li>
1013
1018
</ol>
1014
1019
1015
-
<h3>Phase 5 — launchd swap (3-6 weeks)</h3>
1020
+
<h3>Phase 5 — Apple launchd-842.92.1 clean import (4-8 weeks)</h3>
1021
+
1022
+
<p>Replace <code>freebsd-launchd</code>'s 1,496-LoC minimal rewrite with a clean verbatim import of Apple's last open-source launchd, building against our libmach + libxpc + libdispatch stack and keeping all Mach paths intact (no stripping, unlike <code>freebsd-launchd</code>'s original approach).</p>
1023
+
1024
+
<p><strong>Why this over a ravynOS fork:</strong> same source code either way (ravynOS's launchd descends from NextBSD which descends from Apple <code>launchd-842.x</code>), but a clean import gives us:</p>
1025
+
<ul>
1026
+
<li>Clean provenance — every commit is either "Apple verbatim" or "our patch"</li>
<p><strong>Estimated patch size:</strong> ~700-1500 lines sitting on top of Apple's ~16,500 lines of clean source. Comparable to gershwin's libdispatch patch in approach, larger in absolute size.</p>
<li>Migrate the FreeBSD-15 fixes (per-user env file, audit-session workaround, build flags) from ravynOS's tree.</li>
1019
-
<li>Audit-mark the 36 <code>#if 0</code> / FIXME sites for which need re-enabling on FreeBSD.</li>
1020
-
<li>CI gate: ravynOS-launchd boots a livecd to multiuser, can start/stop a daemon, processes the existing FreeBSD launch.plists.</li>
1021
-
<li>Cut over the ISO build from <code>freebsd-launchd</code> to <code>freebsd-launchd-mach</code> launchd. Keep <code>freebsd-launchd</code>'s minimal daemon around as a fallback for non-Mach-aware deployments.</li>
<li><strong>MIG <code>.defs</code> compilation</strong> — Apple's <code>protocol_jobmgr.defs</code>, <code>job.defs</code>, etc. via a FreeBSD-host <code>mig</code> tool producing our shape of stubs. ~100-200 lines of build orchestration.</li>
1058
+
<li><strong>Mach API compat shims</strong> — Apple's launchd assumes the full XNU Mach ABI (<code>bootstrap_*</code>, <code>mach_port_construct</code>, <code>MACH_NOTIFY_DEAD_NAME</code>, voucher APIs). Our libmach exposes a subset (Phase 1 expansion + Phase 3 bootstrap server). Either widen libmach to cover what launchd needs, or write thin compat shims that route to what we have. ~500-1000 lines.</li>
<li>Phase 2-4 (libxpc) — required, modern launchd routes job management through libxpc</li>
1069
+
<li>Phase 3 (bootstrap server) — or absorbed into this phase; Apple's launchd is itself the bootstrap server</li>
1070
+
</ul>
1071
+
1072
+
<p><strong>Reference NOT fork:</strong> NextBSD's <code>sbin/launchd/</code> and ravynOS's <code>sbin/launchd/</code> are useful prior art — their FreeBSD shims have already solved many of the same problems we'll hit. We can read their patches as guidance, but our patches stay clean-room (commit messages describe the underlying problem, not "ported from NextBSD"). Keep the lineage cleanly "Apple upstream + our patches."</p>
1073
+
1074
+
<p><strong>Test gate (matches Phase B Tier 1's smoke-driven completion criterion):</strong></p>
1075
+
<ol>
1076
+
<li>launchd boots as PID 1 on a livecd</li>
1077
+
<li>Processes <code>org.freebsd.*</code> launch.plists from <code>/System/Library/LaunchDaemons/</code></li>
1078
+
<li>Can start/stop a daemon via <code>launchctl load</code> / <code>launchctl unload</code></li>
1079
+
<li>Bootstrap port-name registration / lookup works (proves the libxpc + bootstrap server integration)</li>
1080
+
<li>System reaches multiuser without panic across at least 100 boot cycles</li>
1081
+
</ol>
1082
+
1083
+
<p><strong>Cutover:</strong> ISO build switches from <code>freebsd-launchd</code> to <code>freebsd-launchd-mach</code> launchd. Keep <code>freebsd-launchd</code>'s minimal daemon around as a fallback for non-Mach-aware deployments (e.g. a stripped-down FreeBSD build that doesn't load mach.ko).</p>
<p>Prerequisite for Phase 6. Per the audit in §9.5, GNUstep libs-corebase has critical gaps that block configd. Build a hybrid CF library that ships with <code>freebsd-launchd</code>:</p>
0 commit comments