Skip to content

Instantly share code, notes, and snippets.

@keithrbennett
Created July 28, 2022 04:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keithrbennett/d95653af91184b9eb9b35d26f8b9b2e8 to your computer and use it in GitHub Desktop.
Save keithrbennett/d95653af91184b9eb9b35d26f8b9b2e8 to your computer and use it in GitHub Desktop.
Illustrates the use of 'trap' in Ruby for crude interprocess communication
#!/usr/bin/env ruby
# Author: @keithrbennett (Github)
# Illustrates how to respond to Unix signals in a Ruby program, using SIGUSR1 and SIGUSR2
# for user-defined signals, and SIGINT for trapping Ctrl-C.
require 'awesome_print'
require 'json'
require 'yaml'
$stderr.puts <<~GREETING
Pid is #{Process.pid}.
Standard output is a #{$stdout.tty? ? 'tty' : 'block'} device.
You can send signals SIGUSR1 and SIGUSR2 (e.g. via `kill`) to poke this program
to output its stats in human readable or YAML forms:
kill -SIGUSR1 #{Process.pid} # Human readable (Awesome/Amazing Print)
kill -SIGUSR2 #{Process.pid} # YAML
...and to terminate the program, outputting the final data observation:
kill -SIGINT #{Process.pid} # Terminate
GREETING
SystemInfo = Struct.new(:pid, :uptime, :res_memory_mb)
# See this great article about monotonic time: https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/
def monotonic_time_now
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
START_TIME = monotonic_time_now
def monotonic_uptime
monotonic_time_now - START_TIME
end
def resident_memory_in_mb
# -o = format with the following data
# rss = resident memory set size, in ?
# h = omit the header ("RSS")
command = "ps -o rss h #{Process.pid}"
output = `#{command}`
kb = output.strip.to_i
(kb / 1024.0).round(0)
end
def system_info
SystemInfo.new(Process.pid, monotonic_uptime.round(2), resident_memory_in_mb)
end
def print_system_info
ap system_info.to_h
end
Signal.trap('USR1') { print_system_info }
Signal.trap('USR2') { puts system_info.to_h.to_yaml }
Signal.trap('INT') do
puts "\nEnding program, final stats are:"
print_system_info
exit
end
# See https://dsa.cs.tsinghua.edu.cn/oj/static/unix_signal.html for signal values.
#Signal.trap(30) { puts 30 }
#Signal.trap(10) { puts 10 }
memory_black_hole = []
loop do
sleep 0.5
memory_black_hole << Array.new(100_000) { Time.now }
#puts "Time count: #{ObjectSpace.each_object(Time).count}"
$stdout.flush
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment