In Progress
Unit 1, Lesson 1
In Progress

Subprocesses Part 7: Soft Limits

Video transcript & code

In the last episode we learned how to set resource limits on new subprocesses. We saw that it's possible to place boundaries on things like total CPU time and memory usage.

pid = Process.spawn "./cpu_asplode.rb", rlimit_cpu: 1
Process.waitpid pid

The drawback of these resource limits is that their effect is both sudden and final. Programs generally don't get a chance to do any recovery when they hit the wall.

But that doesn't have to be the case. When we set rlimits, we have the option of setting both a soft limit and a hard limit. Let's modify our process spawning code. Instead of passing a single integer for the rlimit_cpu option, we'll pass an array of two integers.

pid = Process.spawn "./cpu_asplode2.rb", rlimit_cpu: [1, 2]
Process.waitpid pid

The first number is the soft limit for CPU usage, in seconds. The second number specifies the hard limit.

So what does this buy us? Let's jump over to our CPU-hogging code.

In here, we'll add a trap. We learned about trapping signals in episode #353.

This time, we're going to trap the XCPU signal. In the handler, we'll just output a message do and then do a clean exit.

require "prime"

trap("XCPU") do
  puts "Received SIGXCPU, shutting down..."
  exit
end

Prime.each do |n|
  puts n
end

When we flip to the terminal and run our wrapper script, we can see that it cranks for a while generating primes, and then exits with the message we just added.

But what if we didn't exit? What would happen then?

Let's find out. We'll remove the call to exit, and change the message while we're at it.

We'll also comment out the prime number output, so it doesn't drown out the signal handler output.

require "prime"

trap("XCPU") do
  puts "Can't catch me coppers! Hahahaha!"
end

Prime.each do |n|
  # puts n
end

Then we run our wrapper again.

After a moment, we see the trap message, and after another moment, the program terminates.

What we can see here is that the soft limit acts as a kind of warning; a shot across the program's bow. If it wants to, it can trap the warning signal and handle the situation, either by reducing resource usage, or by doing an orderly shutdown while there are still resources left with which to do it. But once the hard limit hits, the program is killed.

This is just a basic introduction to the concept of soft and hard limits. Different soft limits are handled in different ways on different operating systems. For instance, for some resources, hitting the soft limit may result in errors being raised from system calls rather than in a signal. Consult your operating system's documentation to find out exactly how to detect and handle a given soft limit being triggered.

And that's it for today. Happy hacking!

Responses