Every had that worry that a program will break its bonds and chew up all of your RAM? That worry came face-to-face with me recently, so I decided to do something about it: write a quick utility in Perl6 to solve the problem:
However, first things first: what -is- a memory sentinel?
Simply put, it's something that looks at a process and makes sure it doesn't get too large. If it does, it dies.
These thnigs usually take at least one call to a kernel routine, but for Linux-based systems, it's as simple as looking into the /proc filesystem, so that made things easy. I thought it would be a bit more difficult to write. It wasn't:
perl6 -e 'repeat { (my $p = "/proc/12031/status".IO.slurp) ~~ /"VmRSS:" \s* (\d+)/; say $/[0]; if $/[0].Int > 10500944 { qqx[kill -9 12031]; say "Memory flagged"; exit } ; sleep 30 } while True'
To break it down into something more reusable:
sub MAIN (:$pid, :$gigs) {
# Repeat, infinitely.
loop {
# Query /proc for status of process, and extract memory usage
(my $p = "/proc/{$pid}/status".IO.slurp) ~~ /"VmRSS:" \s* (\d+)/;
# Show current memory usage
say $/[0];
# Check memory usage against our limit, specified by --gigs
if $/[0].Int > ($gigs * 1024 ** 3) {
# It's grown too large, kill it!
qqx[kill -9 $pid];
say "Target memory usage exceeded. Killing process and exiting...";
exit
}
# Wait an appropriate amount of time and try again.
sleep 30
}
}This is just a basic sketch, but if someone finds this useful, then I am more than happy to share.
This feels way to complicated :-) You should just be able to start a thread watching the memory usage of itself and
exiting whenever it is over the limit.Have a look at https://docs.perl6.org/type/ThreadPoolScheduler#(Scheduler)_method_cue and at https://github.com/rakudo/rakudo/blob/master/lib/Telemetry.pm6#L70