This release adds support for cgroup v2. This replaces cgroup v1 support, which lacks functionality and is becoming less widely supported. While Nerves is the current development platform for cgroup support, using cgroups on desktop Linux works but may not be ergonomic. PRs in this area are welcome.
If you don't use cgroups, this update is not breaking for you. Library authors are encouraged to allow both MuonTrap v1 and v2 if your library falls into this category.
-
Breaking changes
- Cgroup v1 support removed
:cgroup_controllersand:cgroup_setsoptions replaced by a single:cgroupconfiguration mapMuonTrap.Daemon.cgget/cgsetAPI changed for v2. They've been de-emphasized for configuration due to their low-level nature
-
New features
- Add new
:cgroupconfiguration option as a more Elixir-friendly configuration method MuonTrap.Daemon.cgroup_config/1returns the daemon's writable cgroup settings as a map keyed by the same atoms accepted by the:cgroupoption, suitable for round-tripping into another daemon.MuonTrap.Daemon.statistics/1now also returns cgroup statistics as a map under the:cgroupkey. Map keys are strings that match cgroup file names exposed by the kernel (memory usage and peak, CPU and memory PSI, OOM-kill counts,pids.current, etc.).MuonTrap.Daemon.cgroup_path/1returns the daemon's cgroup path (ornilif the daemon isn't running under a cgroup).- MuonTrap now uses
cgroup.kill(kernel 5.14+) for atomic cgroup teardown when available, falling back to per-pid SIGKILL on older kernels.
- Add new
The new configuration gives a feel for how the API has changed to reduce manual string-based interactions:
cgroup_controllers: ["memory", "cpu"],
cgroup_sets: [
{"memory", "memory.max", "268435456"},
{"cpu", "cpu.max", "50000 100000"}
]
cgroup: %{
memory_max: 256*1024*1024,
cpu_max: {50_000, 100_000}
}- Fixes
- Fix truncated output when a command exits (Thanks @dcalvo)
- Gracefully handle an already-closed port (Thanks @bencoppock)
- Fix
:epipefailures for commands that produce output. (Thanks @dcalvo!) - Fix test failures on Ubuntu 26.04 and expand CI tests to cover Ubuntu releases and macOS versions. Previously CI only verified Alpine Linux.
- New feature
- Add
:wait_foroption toMuonTrap.Daemon. This lets you specify a function that can block until a file, named pipe, local server, etc. is available before starting the OS process. This simplifies workarounds for OS processes that don't wait or retry on inputs that come up asynchronously.
- Add
- New feature
- Add
:capture_stderr_onlyoption to capture only stderr while ignoring stdout. This is useful when you want to capture error messages but not regular output. Works with bothMuonTrap.cmd/3andMuonTrap.Daemon. (@fermuch)
- Add
- Bug fixes
- Ignore transient EAGAIN, EWOULDBLOCK, and EINTR errors when processing acknowledgments from Erlang. These would cause unneeded restarts. (@mediremi)
- New feature
- Add
:logger_funoption toMuonTrap.Daemonto allow complete customization of the logging process. Pass it a 1-arity function ormfargstuple. This option takes precedence over all of the other log related options. (@bjyoungblood)
- Add
- New feature
- Add Logger metadata in
MuonTrap.Daemon. See the:logger_metadataoption. (@bjyoungblood)
- Add Logger metadata in
- Bug fixes
- Support logging output to all Elixir logger levels. Previously the "new" set that includes emergency, critical, warning, etc. would fail the option check
- Default the
log_transformoption to replace invalid UTF8 characters so they don't crash the Logger. This fixes an annoyance where a program would do this and there'd be log crash spam. It's still overridable, so users using custom loggers that already handle this can passFunction.identity/1to disable. (@jjcarstens)
- New feature
- Add a timeout option to
MuonTrap.cmd/3. OS processes that take too long will be killed and a:timeoutreturn status returned. This is backwards compatible. Thanks to @bjyoungblood for adding this feature.
- Add a timeout option to
-
Bug fixes
- Fix issue where lots of prints from a child process when the Erlang process side is killed can cause MuonTrap to not clean up the child process. There are some potential variations on this that were also fixed even though they were unseen. Thanks to @bjyoungblood for figuring this out.
-
Improvements
- Improve debug logging so that when enabled, fatal errors are written to the log as well and not to stderr.
- Bug fixes
- Fix C compiler error when building with older versions of gcc. This fixes an compile error with Ubuntu 20.04, for example.
- Bug fixes
- Fix regression where stderr would be printed when
stderr_to_stdout: truewas specified and logging disabled.
- Fix regression where stderr would be printed when
-
New feature
- Add flow control to stdout (and stderr if capturing it) to prevent
out-of-memory VM crashes from programs that can spam stdout. The output
would accumulate in the process mailbox waiting to be processed. The flow
control implementation will push back and slow down output generation. The
number of bytes in flight defaults to 10 KB and is set with the new
:stdio_windowparameter. (@jjcarstens)
- Add flow control to stdout (and stderr if capturing it) to prevent
out-of-memory VM crashes from programs that can spam stdout. The output
would accumulate in the process mailbox waiting to be processed. The flow
control implementation will push back and slow down output generation. The
number of bytes in flight defaults to 10 KB and is set with the new
-
Bug fixes
- Fix various minor issues preventing unit tests from passing on MacOS. (@jjcarstens)
- New feature
- Added
:exit_status_to_reasonto theDaemonto be able to change how theDaemonGenServer exits based on the exit status of the program being run. (@erauer)
- Added
- New features
- Support transforming output from programs before sending to the log. See the
new
:log_transformoption. (@brunoro)
- Support transforming output from programs before sending to the log. See the
new
This release only changes the version number. It has no code changes.
This release has no code changes.
- Improvements
- Clean up build prints, fix a doc typo, and update dependencies for fresher docs.
- Bug fixes
- Fix the
:delay_to_sigkilloption so that it takes milliseconds as documented and remove the max delay check. Previously, the code used microseconds for the delay despite the documentation. If you were using:delay_to_sigkill, this is a backwards incompatible change and your delays will be 1000x longer. Thanks to Almir for reporting this issue.
- Fix the
- New features
- Added the
:log_prefixoption to MuonTrap.Daemon so that logged output can be annotated in more helpful ways. This is useful when running the same program multiple times, but with different configurations.
- Added the
This update contains many changes throughout. If you're using cgroups, please review the changes as they likely affect your code.
-
New features
- Added
:cgroup_base. The preferred way of using cgroups now is for MuonTrap to create a sub-cgroup for running the command. This removes the need to keep track of cgroup paths on your own when you run more than one command at a time.:cgroup_pathis still available. - Almost all inconsistencies between MuonTrap.Daemon and MuonTrap.cmd/3 have been fixed. As a result, MuonTrap.Daemon detects and raises more exceptions than previous. It is possible that code that worked before will now break.
- MuonTrap.Daemon sets its exit status based on the process's exit code.
Successful exit codes (exit code 0) exit
:normaland failed exit codes (anything else) do not. This makes it possible to use the Supervisor:temporaryrestart strategy that only restarts failures. - MuonTrap.Daemon supports a
:nameparameter for setting GenServer names. - MuonTrap.Daemon
cggetandcgsethelpers return ok/error tuples now since it was too easy to accidentally call them such that they'd raise.
- Added
-
Bug fixes
- Forcefully killed processes would get stuck in a zombie state until the kill timeout expired due to a missing call to wait(2). This has been fixed.
- Exit status of process killed by a signal reflects that. I.e., a process killed by a signal exits with a status of 128+signal.
- Bug fixes
- Fixed an issue where environment variable lists passed to MuonTrap.Daemon had to be charlists rather than Elixir strings like MuonTrap.cmd/3 and System.cmd/3.
- Bug fixes
- Reverted removal of
child_spec
- Reverted removal of
- New features
- MuonTrap.Daemon can log stderr now as well as stdout. Pass
stderr_to_stdout: truein the options. Thanks to Timmo Verlaan for this update.
- MuonTrap.Daemon can log stderr now as well as stdout. Pass
- Improvements
- Move port process build products under
_build. This fixes an issue where changes in MIX_TARGET settings would not be picked up. - Improved some specs to remove Dialyzer warnings in some cases
- Move port process build products under
- New features
- MuonTrap.Daemon no longer sends all of the output from the process to the
logger by default. If you want it logged, pass in a
{:log_output, level}option. This also slightly improves the logged message to make it easier to read.
- MuonTrap.Daemon no longer sends all of the output from the process to the
logger by default. If you want it logged, pass in a
- Bug fixes
- Make MuonTrap.Daemon usable (child_specs, options)
- Bug fixes
- Make MuonTrap.cmd/3 pass the System.cmd/3 tests
- Add a few more specs and fix Dialyzer errors
- Bug fixes
- Add missing dependency on
:logger
- Add missing dependency on
- Bug fixes
- Fix hex package contents
- Bug fixes
- Fix shutdown timeout and issues with getting EINTR
- More progress on cgroup testing; docs
- Initial release