refactor: introduce Cgroup interface and consolidate cgroupfs operations#23
Merged
Conversation
Promotes the cgroup helpers in cgroup/Cgroup.kt to a Cgroup interface with a CgroupV2 implementation that holds FileSystem in its constructor. Higher layers (Create, Delete, Ps, runMainProcess) now take a Cgroup parameter alongside Syscall/FileSystem and call cgroup.setup / cleanup / getPids instead of free helpers. This is the same pattern as Syscall (#19/#20) and FileSystem (#22): domain code goes through an injected interface so tests can substitute a fake without touching the real cgroupfs. What changes: - cgroup/Cgroup.kt: now just the interface (setup, cleanup, getPids). - cgroup/CgroupV2.kt (new): implementation. Keeps the existing logic including the subtree_control ancestor walk (#17 fix), the cgroup v1 shares -> cgroup v2 weight conversion, the swap.max = swap - limit semantic, and the procs write. - utils/FileSystem.kt gains removeDirectory(path: String): Boolean so cgroup cleanup can drop its direct platform.posix.rmdir/access usage. RealFileSystem implements it via posix rmdir, FakeFileSystem mutates its in-memory directories set. - Main.kt instantiates CgroupV2(fs) once and threads it into create / delete / ps. start / kill / state don't need it. - Tests: - CgroupTest now exercises CgroupV2 directly. New cleanup tests cover the no-op-for-null path and FakeFileSystem-backed directory removal. - FakeCgroup (new) records calls; available for upcoming higher-layer tests of Create / Delete / Ps. No behavior change is intended; integration workflow exercises mount, pivot_root, capabilities, seccomp, and cgroup limits end-to-end.
2 tasks
ternbusty
added a commit
that referenced
this pull request
May 9, 2026
…impls Same pattern as Syscall (#19/#20), FileSystem (#22), and Cgroup (#23) but for IPC. The Main / Init senders/receivers and the NotifyListener / NotifySocket pair become interfaces so domain code can be tested with in-memory fakes that record sent messages and let tests preseed received ones. What changes: - channel/Channel.kt now declares the four message-channel interfaces (MainSender, MainReceiver, InitSender, InitReceiver). Each keeps fd() and close() so the FD-inheritance and lifecycle wiring don't need a separate seam. - channel/SocketChannel.kt (new) holds the Unix-socketpair-backed implementations (SocketMainSender etc.) and the existing private helpers (createSocketPair, sendMessage, sendMessageWithFd, receiveMessageWithFd). The mainChannel / initChannel factories return the interface types but instantiate the Socket* classes. - channel/NotifySocket.kt now declares NotifyListener and NotifySocket as interfaces, with SocketNotifyListener (two constructors: from path and from inherited FD) and SocketNotifySocket as the impls. - Construction sites (Main.kt for the init branch, Create.kt for the initial NotifyListener, Start.kt for the client) reference the Socket* impls directly. Everything else holds the interface type. Tests: - channel/FakeChannel.kt provides FakeMainSender, FakeMainReceiver, FakeInitSender, FakeInitReceiver, FakeNotifyListener, FakeNotifySocket. Senders record every call; receivers consume from preseeded queues. - channel/FakeChannelTest.kt is a sanity check that the fakes record calls and that receivers throw IllegalStateException when an expected message wasn't preseeded — the contract upcoming higher-layer tests will rely on. No production behavior change. The integration workflow exercises the real channel flow end-to-end.
ternbusty
added a commit
that referenced
this pull request
May 9, 2026
…impls (#24) Same pattern as Syscall (#19/#20), FileSystem (#22), and Cgroup (#23) but for IPC. The Main / Init senders/receivers and the NotifyListener / NotifySocket pair become interfaces so domain code can be tested with in-memory fakes that record sent messages and let tests preseed received ones. What changes: - channel/Channel.kt now declares the four message-channel interfaces (MainSender, MainReceiver, InitSender, InitReceiver). Each keeps fd() and close() so the FD-inheritance and lifecycle wiring don't need a separate seam. - channel/SocketChannel.kt (new) holds the Unix-socketpair-backed implementations (SocketMainSender etc.) and the existing private helpers (createSocketPair, sendMessage, sendMessageWithFd, receiveMessageWithFd). The mainChannel / initChannel factories return the interface types but instantiate the Socket* classes. - channel/NotifySocket.kt now declares NotifyListener and NotifySocket as interfaces, with SocketNotifyListener (two constructors: from path and from inherited FD) and SocketNotifySocket as the impls. - Construction sites (Main.kt for the init branch, Create.kt for the initial NotifyListener, Start.kt for the client) reference the Socket* impls directly. Everything else holds the interface type. Tests: - channel/FakeChannel.kt provides FakeMainSender, FakeMainReceiver, FakeInitSender, FakeInitReceiver, FakeNotifyListener, FakeNotifySocket. Senders record every call; receivers consume from preseeded queues. - channel/FakeChannelTest.kt is a sanity check that the fakes record calls and that receivers throw IllegalStateException when an expected message wasn't preseeded — the contract upcoming higher-layer tests will rely on. No production behavior change. The integration workflow exercises the real channel flow end-to-end.
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.
Summary
Same pattern as the Syscall (#19 / #20) and FileSystem (#22) refactors but for the cgroup operations.
setup/cleanup/getPids.FileSystemin its constructor. Preserves the existing logic verbatim — the subtree_control ancestor walk (#17 fix), v1-shares-to-v2-weight conversion,swap.max = swap - limitsemantic.removeDirectory(path: String): Booleanso cgroup cleanup can stop callingplatform.posix.rmdir/accessdirectly.RealFileSystemimplements it via posixrmdir;FakeFileSystemmutates its in-memorydirectoriesset.Main.ktinstantiatesCgroupV2(fs)once and threads it intocreate/delete/ps.start/kill/statedon't need it.Tests
setupCgroup(fs, ...)toCgroupV2(fs).setup(...). Three newcleanuptests cover the null-path no-op andFakeFileSystem-backed directory removal.deleteinvokescgroup.cleanupfor the right path).Test plan
buildworkflow passes (compile + ktlint + kotest, including the migrated cgroup tests)integrationworkflow still passes — production-side this is a name change plus indirection throughCgroup/CgroupV2; the actual cgroupfs operations are unchanged