Upload
awwaiid
View
117
Download
2
Embed Size (px)
DESCRIPTION
As presented at RubyConf 2014 (San Diego). Lots of live coding, I'll link the video eventually. ABSTRACT: Ever type 'next' into your debugger and then realize you should have used 'step'? Or perhaps invoked a method that you wish you could take back? Regret no more! Just turn the clock back a few ticks and begin again! With only a few restrictions and side-effects we will learn how to construct and use a time machine. WARNING: Time travel may cause zombies. Github: https://github.com/awwaiid/pry-timetravel RubyGems: https://rubygems.org/gems/pry-timetravel
Citation preview
For each universethere are a dozen others;one must lack my bug?
A Partial-Multiverse Modelof Time Travelfor Debugging
RubyConf 2014
Brock [email protected]@optoro.com
awwaiid@rbconf:~$ whoami
Debuggers
pry-byebug
How does THAT work‽
Sweet
OK. What could be better?
MAD SCIENCE
pry-timetravel
And we're done!
The Idea
(nothing new under the sun)
fork() the universe during 'next'
Suspend the child fork
Keep track of all created child forks
Upon 'back', grab the most recent child fork
Resume (time-travel!) the previous child fork
Wha?
Two essential ingredients.
Unix fork()
New child process:
new (child) PIDcopy of memoryshare file handles (sockets)... other stuffruns separately
Copy-On-Write!
Signals
Registered OS callbacks
SIGINT
SIGTERM
SIGKILL
SIGHUP
SIGUSR1
SIGALRM
SIGTSTP
SIGINT (^C)
SIGTERM (kill)
SIGKILL (kill -9)
SIGHUP (daemon reload)
SIGUSR1 (... things ...)
SIGALRM (just another 5 minutes!)
Signal handling / sending in Ruby
SIGTSTP (^Z)
SIGSTOP
SIGCONT
def snap if child_pid = fork # I am the parent! Process.kill 'SIGSTOP', $$ else # I am the child! @snap_pid.push child_pid endend
def restore Process.kill 'SIGCONT', @snap_pid[-1] Process.kill 'SIGSTOP', $$end
Limitation:
Shared file handles (inc. sockets!)
Limitation:
External state.
Limitation:
Threads. Not so much.
Limitation:
Can only travel back to checkpoints
(see also: Primer)
Limitation:
Might crash the multiverse throughmemory exhaustion. I guess.
Wrap in a pry pluginand we're done, right?
Complication:
Shell detects STOP
awwaiid@floyd:~$ pry[1] pry(main)>zsh: suspended (signal) pry
Fix:
Make a dummy parent processthat just sleeps (or sig-pause)
Complication:
Killing parent snapshots
Fix:
Let the One True (parent) snapshotkill all of its children (via SIGUSR1).
(also: nope. totally wrong.)
Complication:
Every snapshot wants to clean up
Fix:
If you are not the current snapshot,terminate yourself without cleanup!
Complication:
ZOMBIES
Zombie:
Child process that has exited nicelybut then the parent exited not-nicely.
The process is dead, yet remains.
Great. Now we can go back!
I WANT MOAR
Tree of snapshots
TODO: auto-snapshot
References:
https://github.com/TomOnTime/timetravelpdb
http://programmers.stackexchange.com /questions/181527 /why-is-reverse-debugging-rarely-used
http://debug.elm-lang.org/
If I had the chanceI'd write a better haikuoh wait, I HAVE A TIME MACHINE
THE END