Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dispelling the Dark Magic: Inside a Ruby Debugger

Daniel Azuma
November 16, 2017

Dispelling the Dark Magic: Inside a Ruby Debugger

Presentation by Daniel Azuma at RubyConf 2017. Covers how to implement a basic debugger for Ruby programs, and discusses some techniques behind the Stackdriver Debugger for Ruby. See also the live coding artifact at https://github.com/dazuma/google-snippets/blob/master/mini-debug

Daniel Azuma

November 16, 2017
Tweet

More Decks by Daniel Azuma

Other Decks in Programming

Transcript

  1. Dispelling the dark magic:
    inside a Ruby debugger
    Daniel Azuma
    November 16, 2017

    View Slide

  2. photo by Daniel Azuma

    View Slide

  3. https://eclipse2017.nasa.gov/eclipse-who-what-where-when-and-how

    View Slide

  4. https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer.html

    View Slide

  5. Live coding!? OMG!!

    View Slide

  6. Live coding!? OMG!!

    View Slide

  7. Daniel Azuma
    http:/
    /daniel-azuma.com/

    View Slide

  8. View Slide

  9. Lawyercat says:
    Code samples are:
    Copyright 2017 Google Inc.
    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this code except in compliance with the License. You may obtain a copy of
    the License at:
    https://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing, software distributed
    under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
    OR CONDITIONS OF ANY KIND, either express or implied. See the License for
    the specific language governing permissions and limitations under the License.

    View Slide

  10. Breakpoints by file/line
    Command shell
    Step in/out/over
    Debugger features

    View Slide

  11. ( Live coding session )

    View Slide

  12. TracePoint

    View Slide

  13. TracePoint.trace :call do |tp|
    puts "Called method #{tp.method_id}"
    end

    View Slide

  14. line
    class
    end
    call
    return
    c_call
    c_return
    raise
    b_call
    b_return
    thread_begin
    thread_end
    fiber_switch
    TracePoint event types

    View Slide

  15. line
    class
    end
    call
    return
    c_call
    c_return
    raise
    b_call
    b_return
    thread_begin
    thread_end
    fiber_switch
    TracePoint event types

    View Slide

  16. ( Live coding session )

    View Slide

  17. Inception (2010) © Warner Bros.
    https://commons.wikimedia.org/wiki/File:Solar_eclipse_1878Jul29-Corona_Pikes_peak_Langley.png

    View Slide

  18. Stackdriver
    Debugger

    View Slide

  19. https://commons.wikimedia.org/wiki/File:Lunar_eclipse_al-Biruni.jpg
    Threads

    View Slide

  20. TracePoint.trace :call do |tp|
    puts "Called method #{tp.method_id}"
    end

    View Slide

  21. void rb_thread_add_event_hook(VALUE thval,
    rb_event_hook_func_t func,
    rb_event_flag_t events,
    VALUE data);
    int rb_thread_remove_event_hook(VALUE thval,
    rb_event_hook_func_t func);

    View Slide

  22. Ruby interface to
    thread-scoped
    TracePoint call?

    View Slide

  23. https://commons.wikimedia.org/wiki/File:Astronomy;_a_view_of_London_in_1748,_with_diagrams_of_an_ecl_Wellcome_V0024734.jpg
    Speed

    View Slide

  24. file_events = [:call, :b_call, :return,
    :b_return, :fiber_switch]
    TracePoint.trace *file_events do |tp|
    if @breakpoint_files.include? tp.path
    @line_trace.enable
    else
    @line_trace.disable
    end
    end

    View Slide

  25. View Slide

  26. Native
    breakpoint API?

    View Slide

  27. https://commons.wikimedia.org/wiki/File:Macrobius,_lunar_and_solar_eclipse.jpg
    Side effects

    View Slide

  28. Object state changes
    External side effects
    Side effects

    View Slide

  29. BYTE_CODE_BLACKLIST = %w(
    setinstancevariable
    setclassvariable
    setconstant
    setglobal
    defineclass
    opt_ltlt
    opt_aset
    opt_aset_with
    ).freeze

    View Slide

  30. C_METHOD_WHITELIST = %w(
    Array#+
    Array#-
    Array#==
    Array#any?
    Array#assoc
    Array#at
    Array#bsearch
    # etc...

    View Slide

  31. View Slide

  32. Immutability?

    View Slide

  33. Immutability?
    Code jails?

    View Slide

  34. Immutability?
    Code jails?
    Guilds??

    View Slide

  35. View Slide

  36. Debuggers (the basics)
    are straightforward!

    View Slide

  37. Ruby has partial
    support for debuggers

    View Slide

  38. Try out a debugger!
    Byebug: interactive debugger shell
    https://github.com/deivid-rodriguez/byebug
    Stackdriver debugger: for live web applications
    https://cloud.google.com/debugger
    https://github.com/GoogleCloudPlatform/google-cloud-ruby/tree/
    master/google-cloud-debugger

    View Slide

  39. It's just Ruby

    View Slide

  40. Thanks for viewing!
    Daniel Azuma
    [email protected]
    @danielazuma

    View Slide