Contributing
Bug fixes, tests and ports are welcome. A change should come with a test that fails without it.
Before you send a change
make check analyze verif-sim format-checkmake check: unit, CLI and integration tests (SKIP_INTEGRATION=1for the unit tests only).make analyze:gcc -fanalyzer, which must be silent, and clang-tidy.make verif-sim: the model-checking harnesses as random tests.make format-check:.clang-format(4 spaces, attached braces,char *p, 120 columns).make formatrewrites files. CI pins clang-format 18, because the output differs between major versions.- If you changed the controller, the process table or an iterator, also run
sh tools/mutation.sh; every mutant must still be killed, and a new defect class deserves a new mutant intools/mutants.txt.
Rules of the code base
- Architecture first. The module rules and invariants in ARCHITECTURE.md are normative: a change that breaks one changes that document in the same commit. Only
src/main.ccallsexit(); onlysrc/platform/*/iterator.cknows an operating system. - Compatibility. Options, exit statuses and log text are the public interface of 1.x. A change a script could notice is listed in Upgrading and the changelog.
- Say what is not tested. Code that was written without a host to run it on is labelled that way in the source, the changelog and Platforms. A claim in the docs is a statement about a run that happened.
- Original code. Contributions are GPL-2.0-or-later. New files carry the copyright and
SPDX-License-Identifier: GPL-2.0-or-laterheader used in the tree; contributors are credited inAUTHORS.
Adding a platform
- Create
src/platform/<os>/iterator.cwithinit_process_iterator,get_next_processandclose_process_iterator, and add its branch tosrc/platform/iterator.cand the fields it needs tostruct process_iteratoriniterator.h. - Fill
struct process: pid, parent pid, a start time that is stable for the life of a process and only ever compared for equality, and CPU time in milliseconds. Document the units initerator.h. - Copy the processes into an array whose records start with
struct snap_recand callsnapshot_select(recs, n, sizeof(*recs), filter->pid, filter->include_children). - Skip zombies and kernel threads. Check what your kernel really reports for them: OpenBSD listed zombies, and a limiter that waits for them never finishes.
- Check how the CPU clock advances. A counter that only moves when a process is switched out (OpenBSD's
p_rtime) makes the controller see steps, not a rate. - Add a job to
.github/workflows/vm.ymlif a VM exists for it (tools/vm_build.shbuilds and tests inside the guest and keeps the transcript), and update Platforms with what actually ran.
Sending a change
Open a pull request at GitHub, or send a patch from git format-patch. Keep commits focused, explain the reason and the evidence (which test fails before and passes after) in the message, and do not mix a reformat with a behaviour change.