Talks
mruby-rr: Time Traveling Debugger For mruby Using rr
Summarized using AI

mruby-rr: Time Traveling Debugger For mruby Using rr

by Lin Yu Hsiang

In this RubyKaigi talk, Lin Yu Hsiang introduces mruby-rr, an innovative time-traveling debugger specifically designed for mruby, utilizing the Mozilla rr backend. The session addresses the common challenges developers face when dealing with elusive bugs that are difficult to reproduce, such as race conditions and time-related errors. Unlike traditional debuggers, mruby-rr allows developers to not only set breakpoints but also to 'rewind' and inspect earlier states of execution, making debugging more efficient and consistent.

Key Points Discussed:

  • Use Case: Difficult Bugs

    • Common issues include race conditions, UI-related bugs, and time-related discrepancies.
    • Reproducing errors that rely on specific timing or randomness poses a significant challenge.
  • Traditional Debugging Limitations

    • Standard debuggers like mrdbt.rb do not allow navigating backward in execution, making it tough to trace variable states.
  • Introduction of mruby-rr

    • Mruby-rr utilizes rr's recording and replay capabilities to allow time travel through program execution.
    • It supports varying operations like reverse-next, reverse continue, and expression evaluation.
  • Functionality

    • The recording process captures program behavior, while replay lets developers evaluate variables at any previous execution point.
    • Exceptional features include restarting from recorded data, making consistent reproduction of bugs achievable.
  • Installation and Configuration

    • Developers must include mruby-rr in their build configuration and ensure that debugging support is enabled before building from the source.
    • Essential commands include 'record' and 'replay' to manage the debugging process effectively.
  • Technical Considerations

    • Supported only on Intel CPUs running Linux due to the reliance on ptrace.
    • Performance may vary, especially in multi-core environments.
  • Future Prospects

    • Upcoming improvements aim for more complete feature sets in mruby-rr to match those of rr and better replay performance while maintaining breakpoints.

Mruby-rr signifies a significant advancement in debugging within the mruby ecosystem, facilitating easier identification and resolution of complex bugs. The speaker encourages the audience to explore mruby-rr available on GitHub and to reach out via Twitter for further queries. The overarching takeaway is that time-traveling debugging is now possible with mruby, greatly enhancing developers' capabilities in managing software errors.

00:00:01.760 Hello everyone, welcome to my RubyKaigi talk. Today, I'm going to talk about mruby-rr, a time-traveling debugger for mruby using rr.
00:00:06.799 So, about me: I'm Lin Yu Hsiang from Taiwan, and my Twitter handle is @johnlee_bc. I'm a senior solution architect at West Pharmaceutical.
00:00:12.240 Today's agenda includes: first, an introduction to the use case for mruby-rr; then, I'll discuss the internals of mruby and rr; afterwards, I'll show the benchmarks; and finally, I will outline future work.
00:00:30.960 There are some bugs that are hard to reproduce in our common mruby programs. One of the most notorious is the race condition. This occurs when multiple threads or fibers are competing for some variables or data, making it difficult to reproduce the timings correctly.
00:00:46.399 Another type of bug is user interface-related, which requires specific user inputs, such as clicking certain buttons or following specific sequences. The third type is related to randomness; if you're using random data, reproducing the exact same scenario becomes challenging.
00:01:02.159 Time-related bugs can also be problematic, especially when they involve time now. Once time passes, it's impossible to go back. For instance, if we have a variable that captures the current time before running some processes, we might expect consistent results over two executions. However, if the code is faulty, the results will differ.
00:01:17.680 Using the standard mruby debugger, let's see how we can trace this issue. First, we'll invoke mruby with mrdbt.rb and set a breakpoint at line 2 of t.rb. We've chosen line 2 because the variable won't have a value assigned until then. After continuing execution, we can evaluate the value of variable 'a' at that point.
00:02:19.520 However, once we reach line 4, we cannot revert back to line 1, as there's no time machine to help us. So, what do we do? We need to find that time machine! In the programming world, this concept does exist; we call it a time-traveling debugger. Time travel debugging allows you to step back in time through the source code to understand what happened during execution. Essentially, it has all the functions of a standard debugger—breakpoints, continues, evaluations—with the added feature of reverse execution.
00:04:08.560 Today, I'm introducing mruby-rr, an experimental mruby time-traveling debugger that utilizes rr as its backend. I created mruby-rr as a proof of concept to demonstrate that time-travel debugging is indeed possible in Ruby. Mruby-rr uses record and replay functionalities to navigate and inspect programs, and it operates on Intel CPUs and Linux.
00:05:30.960 To trace a program with mruby-rr, we first record the program using `record` and pass the required arguments through a script file. While running the program, we collect output and store trace data.
00:06:25.760 Next, we run the replay command. After starting mruby-rr, we can tell it to break at line 2 of t.rb, establishing a breakpoint there. Continuing execution, we’ll evaluate the value of 'a' at that line. When we reach line 4, we again break to inspect the modified value of 'a'. Notably, once we reach line 4, we can use reverse continue to go back, allowing us to evaluate the value of 'a' again at its previous state.
00:07:44.480 The significant advantage here is that in mruby-rr, we can reverse our execution flow. This means we can go back in time until we hit another breakpoint and evaluate 'a' at that point.
00:08:40.240 Another remarkable feature of mruby-rr is that you can restart from recorded trace data. You can instruct it to start over from the beginning, and you will see that it retains the exact data from the previous execution, enabling consistent bug reproduction even for elusive bugs.
00:09:24.560 Now, how can you get your hands on this time machine called mruby-rr? First, you need to install it, which depends on rr. We'll discuss that later. The first step is to add mruby-rr to your build configuration for mruby and enable debugging support by adding 'ENABLE_DEBUG'. You need to set up the debug hook correctly to facilitate the debugging process.
00:10:30.720 After adding the necessary components to your configuration, you'll build mruby from source. Cloning the mruby repository will provide you with the debugger binaries. The basic commands for mruby-rr include 'record' for executing the script file and 'replay' for running the recorded trace.
00:12:01.839 The primary features of mruby-rr include setting breakpoints, stepping through the code, continuing execution, and evaluating expressions. Additional commands for time traveling include reverse continue and reverse next. These functionalities give you the ability to manipulate the execution flow, making debugging significantly easier.
00:12:44.960 To illustrate how mruby-rr works, we start by launching the debugger, which then starts a mruby process. The rr backend collects and stores various execution information such as breakpoints. The rr library, designed by Mozilla, is fast and efficient, making it suitable for time-travel debugging.
00:14:29.440 It's essential to understand how rr captures execution data. It intercepts system calls, recording both the parameters and results. The timing of these calls is also critical, allowing the debugger to reconstruct the program's execution state accurately, even in the presence of bugs.
00:16:53.440 Despite the capabilities of rr, there are limitations. rr is specific to Intel CPUs and operates only on Linux due to its reliance on ptrace. Additionally, execution is confined to a single core, which may affect performance for multi-core environments.
00:18:25.760 Communication between mruby-rr and rr is managed through the gdbmi interface. The user interface allows for interactions through command inputs and outputs, simplifying the debugging process. Features like breakpoints and evaluations enhance the debugging experience, enabling developers to delve deep into code execution.
00:19:25.440 Current issues with mruby-rr include limitations in recreating alternative execution states and several features still pending implementation. Replay speeds can reduce significantly if breakpoints are enabled.
00:21:14.880 Future work for mruby-rr includes completing the full set of features, aiming for similar capabilities as the underlying rr. There's also a focus on improving performance during replay with breakpoints and potentially adapting the code fetch hook for broader use within the mruby ecosystem.
00:22:47.120 To summarize, mruby-rr makes time-traveling debugging easier, and it is now possible to achieve this functionality within mruby. Thank you for listening to my talk today. You can find mruby-rr on GitHub, and feel free to reach out to me on Twitter at @johnnybc.
00:24:05.440 Thank you, everyone. Goodbye!
Explore all talks recorded at RubyKaigi 2020 Takeout
+17