service: the daemon needs more than launchd's default descriptors - #78
Merged
Merged
Conversation
The Mac daemon died with `Error: Too many open files (os error 24)`. It is in `service.err.log` on Silber. WHY. `render_launch_agent_plist` writes `SoftResourceLimits` ONLY when the operator passes `--memory-max-mb`, and even then it writes only `ResidentSetSize`. `NumberOfFiles` appears nowhere. So a fabric agent inherits launchd's own default, which is small, and nobody chose it. That default is not a ceiling anybody picked for this process. The daemon holds a QUIC endpoint, a connection per peer, a control socket, a dial socket per tunnel, and the files it is syncing. A DESCRIPTOR CEILING IS NOT OPTIONAL, so it is now always written. The resident-set ceiling stays opt-in and unchanged: launchd treats ResidentSetSize as a reclaim preference rather than a kill, but it is still a fixed number, and shipping one by default declares a healthy working set nobody has measured. 8192 IS NOT A MEASUREMENT AND I AM SAYING SO. It is far above any working set this daemon has shown; the entry syncing 17,600 files sat at a few dozen descriptors. The point is to remove an arbitrary small number, not to install a different arbitrary number close enough to matter. I ALSO ADDED A CHECK THAT THE PLIST IS A PLIST. A malformed one does not fail a string assertion, it fails at install time on somebody's machine. `rendered_plists_are_valid_property_lists` renders both branches and hands them to `plutil -lint`. I proved it can fail by injecting an unclosed tag: plutil rejected the plist for memory_max_mb=None: (Encountered unknown tag unclosed on line 31) Off a Mac there is no `plutil`, so it says the plist was not linted rather than passing silently as though it had been. NOT APPLIED TO THE RUNNING SERVICE YET. The plist on disk is the one the old build wrote; it takes a `fabric service install` to replace it, and machine runtime belongs to root, so I will tell `Silber.root` before touching the launchd job. Agent: Silber.fabric
myobie
added a commit
that referenced
this pull request
Aug 25, 2026
#78 gave the launchd plist a `NumberOfFiles` because the Mac daemon had died of `Too many open files`. The systemd unit has the same omission and I only fixed one side, which is how a defect keeps a door open. `LimitNOFILE` appeared nowhere in `render_systemd_user_unit`, so a Linux agent inherits whatever the user manager defaults to. MEASURED ON BOTH PEERS RATHER THAN ASSUMED. Linux is not in the same trouble the Mac was, and that is worth stating plainly: hetz soft 1024, hard 524288, 53 descriptors in use droppy soft 1024, hard 524288, 27 descriptors in use 1024 is four times launchd's default and neither peer has come close to it. So this is not a fire. It is the same inherited-number problem, and 1024 is still a ceiling nobody picked for a daemon that holds a QUIC endpoint, a connection per peer, a control socket and a dial socket per tunnel. 8192 matches the plist, and it is not a measurement there either. Both platforms now state the ceiling instead of inheriting one. Agent: Silber.fabric
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Mac daemon died with
Error: Too many open files (os error 24)— it's inservice.err.logon Silber.Why
render_launch_agent_plistwritesSoftResourceLimitsonly when the operator passes--memory-max-mb, and even then onlyResidentSetSize.NumberOfFilesappears nowhere, so a fabric agent inherits launchd's own default, which is small and which nobody chose for this process.The daemon holds a QUIC endpoint, a connection per peer, a control socket, a dial socket per tunnel, and the files it is syncing.
What changed
A descriptor ceiling is not optional, so it is now always written. The resident-set ceiling stays opt-in and unchanged — launchd treats
ResidentSetSizeas a reclaim preference rather than a kill, but it is still a fixed number, and shipping one by default declares a healthy working set nobody has measured.8192 is not a measurement, and saying so matters. It is far above any working set this daemon has shown — the entry syncing 17,600 files sat at a few dozen descriptors. The point is to remove an arbitrary small number, not to install a different arbitrary number close enough to matter.
A check that the plist is actually a plist
A malformed plist doesn't fail a string assertion — it fails at install time on somebody's machine.
rendered_plists_are_valid_property_listsrenders both branches and hands them toplutil -lint.I proved it can fail by injecting an unclosed tag:
Off a Mac there's no
plutil, so it reports that the plist was not linted rather than passing silently as though it had been.Not applied to the running service
The plist on disk is the one the old build wrote; replacing it takes a
fabric service install. Machine runtime belongs to root, so I'll tellSilber.rootbefore touching the launchd job.Agent: Silber.fabric