rubydebuggingnon-deterministic

Is there a way to save execution of ruby code to debug it using step by step replay later?


I have a rarely reproduced bug in ruby code. By running my test suite constantly I get it once every 10-15 minutes.

What I want to do is to have the execution recorded step by step and once it fails, go ahead and debug what happened.

I know about https://rr-project.org/ and I used it to debug such things in C++. It basically gives you a complete gdb interface into a recorded replay. Something along the same lines would be great.


Solution

  • There is a recording functionality:

    # intermittent.rb
    
    require "debug"
    
    # figure out your break condition
    binding.b do: "catch TypeError"
    binding.b do: "record on"
    # this is slow ^
    
    class M
      def m
        var = rand(10)
        var = "1" if rand(1000) == 666
        var
      end
    end
    
    loop do
      M.new.m + 1
    end
    

    Never really used it, but you can step back:

    $ ruby ./intermittent.rb
    Stop by #0  BP - Catch  "TypeError"
    
    (rdbg) step back
    [replay] [6, 15] in ./intermittent.rb
    [replay]      6| 
    [replay]      7| class M
    [replay]      8|   def m
    [replay]      9|     var = rand(10)
    [replay]     10|     var = "1" if rand(1000) == 666
    [replay] =>  11|     var
    [replay]     12|   end
    [replay]     13| end
    [replay]     14| 
    [replay]     15| loop do
    [replay] =>#0   M#m at ./intermittent.rb:11
    [replay]   #1   block in <main> at ./intermittent.rb:16
    [replay]   # and 2 frames (use `bt' command for all frames)
    
    (rdbg) info
    [replay] %self = #<M:0x00007f946d07ef28>
    [replay] var = "1"
    
    (rdbg) step back
    (rdbg) info
    [replay] %self = #<M:0x00007f946d07ef28>
    [replay] var = 2
    # etc...
    

    https://github.com/ruby/debug