= Control groups in Spectrum // SPDX-FileCopyrightText: 2026 Demi Marie Obenour // SPDX-License-Identifier: GFDL-1.3-no-invariants-or-later OR CC-BY-SA-4.0 https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html[Linux control groups] (cgroups) can be used for several purposes: 1. Waiting for a group of processes to exit. 2. Terminating a group of processes. 3. Limiting a group of processes' access to resources. Spectrum currently uses the first two. The third is not yet used, but will be in the future. == Control Group Hierarchy Spectrum uses the following cgroup hierarchy: 1. There is a `+/vm-services.slice+` cgroup that contains all the per-VM services on the system. 2. The per-VM services for each VM are under `+/vm-services.slice/vm-${VM}.slice+`, where `+${VM}+` is replaced by the VM's ID. 3. Each per-VM service is under `+/vm-services.slice/vm-${VM}.slice/${SERVICE_NAME}+`, where `+${VM}+` is replaced by the VM's ID and `+${SERVICE_NAME}+` is replaced by the name of the service. 4. The virtual machine monitor (VMM) runs under `+/vm-services.slice/vm-${VM}.slice/vmm+`. If a cgroup contains child cgroups, it likely contains a `$inner.service` cgroup. This is where programs that would otherwise run in the cgroup itself are placed. Generally, these programs are instances of https://skarnet.org/software/s6/s6-svscan.html[`s6-svscan`] or https://skarnet.org/software/s6/s6-supervise.html[`s6-supervise`]. == Using Control Groups Most services should be placed in a control group, with only a few exceptions: 1. Services, such as `getty`, that spawn background processes. 2. Loggers. 3. Trivial services where cgroups are unnecessary. === Setting Up Control Groups Generally, it's best to set the control group up as the first thing the service does using Spectrum's https://spectrum-os.org/git/spectrum/tree/tools/cgroup-setup[`cgroup-setup`] tool. To do that, use `+cgroup-setup --leaf -- $1 COMMAND_LINE+`, where `+$1+` should be the service name and `+COMMAND_LINE+` is the program to run in a cgroup. If the control group starts with `/`, it is interpreted as a path relative to `/sys/fs/cgroup`. Otherwise, it is relative to the current control group the program is in. For example, using https://skarnet.org/software/execline/[execline] for your run script: [source,execline] .... #!/bin/execlineb -WS1 # Often, your cgroup is just the parent cgroup # with the name of the service ($1) appended. cgroup-setup --leaf -- $1 # The rest of the script goes here. .... === Purging Control Groups If the service exits, it's usually best to terminate any programs left behind with `SIGKILL` and remove the control group. To do this, make the `finish` script invoke `cgroup-purge`. Its sole command-line argument is the cgroup to remove. [source,execline] .... #!/bin/execlineb -WS3 # Use the same path you used in the run script. cgroup-purge $3 # The rest of the script goes here. .... One can also use `cgroup-purge` to purge a cgroup explicitly. This is used to stop the VMM and all per-VM services when a VM is shut down. == Future plans Control groups are designed around a single writer process controlling each of them. Many Linux distros use systemd for this, but Spectrum doesn't use systemd. The only persistent per-service process is s6-supervise, but that doesn't have control group support. Instead, the plan is to have a database containing this information. Whether this will be in the `data/` subdirectory of the service directory or a separate system-wide database has not yet been determined.