pry-timetravel 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d28f753687e1f5f96c87e7ce51949dc68d8fab6
4
- data.tar.gz: be676c5cc7e8ff236314b31e6161aef76ce017a4
3
+ metadata.gz: 036cd80689a69996c2e965251b5eea0d8ad65958
4
+ data.tar.gz: 4469ac880bb66bcea64873f4cc423f06c2603a76
5
5
  SHA512:
6
- metadata.gz: c42224c2d9c89770cf5f22c861b37fa254a71713d11c46696fbc6d912027f21454a0ea98688f13f690a69e7fc7a5e12b8a1c63e2b2d61603c7c192bbebfb0c01
7
- data.tar.gz: 27bfcc69e86ff9838820f350c5fb617e24d6d1c456e702b670c8c25d7156b9afdb5be0c728b9416f8645696759c4482930e3f0f9e309344635fc9638b2636fed
6
+ metadata.gz: 948b4b85a37039e6829ff9a511ce3cf9c40f3c28d10b0f62e3d9726089c7e2280a9350553f903e15cbce77a36efc5334a1cd917a6c0cb23c0e35fd835204c727
7
+ data.tar.gz: c045d71745d255a7e3c37978cc212a666cde0e40adb625deded075b8323283fc12c070b7377e7b8dcbb3267ba50c05cc97e43f24740d8e6c1c95d62b92e62a75
data/README.md CHANGED
@@ -26,6 +26,27 @@ There are a few more details, but that is the important bit.
26
26
 
27
27
  WARNING: Time travel may cause zombies.
28
28
 
29
+ ## KNOWN ISSUES
30
+
31
+ ### Redis fork detection
32
+
33
+ Redis checks to see if you forked and yells at you about needing to reconnect.
34
+ Reasonably so, as it is a crazy idea to use the same connection in forked
35
+ children! But we are doing crazy things. In 3.1.0 the gem will auto-reconnect,
36
+ or you can pass inherit_socket to the connection to stop that. Or you can do
37
+ this to bypass safety measures:
38
+
39
+ class Redis
40
+ class Client
41
+ def ensure_connected
42
+ yield
43
+ end
44
+ end
45
+ end
46
+
47
+ Maybe this will be a default hack that gets activated on your first snapshot at
48
+ some point in the near future.
49
+
29
50
  ## Meta
30
51
 
31
52
  Released under the MIT license, see LICENSE.MIT for details. License is
@@ -1,7 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'pry'
3
+ require 'json'
3
4
 
4
- require File.expand_path('../pry-timetravel/commands', __FILE__)
5
+ require_relative 'pry-timetravel/commands'
5
6
 
6
7
  class PryTimetravel
7
8
  class << self
@@ -23,92 +24,142 @@ class PryTimetravel
23
24
  end
24
25
 
25
26
  def enter_suspended_animation
27
+ dlog("Installing SIGCONT trap")
26
28
  old_sigcont_handler = Signal.trap('CONT') do
27
29
  dlog("Got a SIGCONT")
28
30
  end
29
31
 
32
+ dlog("Installing SIGEXIT trap")
30
33
  old_sigexit_handler = Signal.trap('EXIT') do
31
34
  dlog("got EXIT")
32
- Kernel.exit!
35
+ Kernel.exit! true
33
36
  end
34
37
 
35
38
  dlog("Stopping myself")
36
39
  Process.kill 'SIGSTOP', $$
37
40
  dlog("Back from SIGSTOP!")
38
41
 
42
+ @snap_tree = JSON.parse(File.read("/tmp/timetravel_#{$root_parent}.json"))
43
+
39
44
  dlog("Returning to old SIGCONT")
40
- Signal.trap('CONT', old_sigcont_handler)
45
+ Signal.trap('CONT', old_sigcont_handler || "DEFAULT")
46
+
41
47
  dlog("Returning to old SIGEXIT")
42
- Signal.trap('EXIT', old_sigexit_handler)
48
+ Signal.trap('EXIT', old_sigexit_handler || "DEFAULT")
43
49
  end
44
50
 
45
- def snapshot
51
+ def start_root_parent
52
+ $root_parent = $$
53
+ child_pid = fork
54
+ if child_pid
55
+ Signal.trap('INT') do
56
+ dlog("root-parent got INT, ignoring")
57
+ end
58
+ Signal.trap('USR1') do
59
+ dlog("root-parent got USR1, exiting")
60
+ FileUtils.rm("/tmp/timetravel_#{$root_parent}.json")
61
+ Kernel.exit! true
62
+ end
63
+ dlog "Root parent waiting on #{child_pid}"
64
+ # sleep
65
+ # Process.waitall
66
+ Process.waitpid child_pid
67
+ # Process.waitpid 0
68
+ dlog "Root parent exiting after wait"
69
+ FileUtils.rm("/tmp/timetravel_#{$root_parent}.json")
70
+ Kernel.exit! true
71
+ end
72
+ end
73
+
74
+ def snapshot(target, parent = -> {}, child = -> {})
46
75
 
47
76
  # We need a root-parent to keep the shell happy
48
77
  if ! $root_parent
49
- $root_parent = $$
50
- child_pid = fork
51
- if child_pid
52
- Signal.trap('INT') do
53
- dlog("root-parent got INT")
54
- end
55
- Signal.trap('USR1') do
56
- dlog("root-parent got USR1")
57
- Kernel.exit!
58
- end
59
- dlog "Root parent waiting on #{child_pid}"
60
- Process.waitpid child_pid
61
- dlog "Root parent exiting!"
62
- Kernel.exit!
63
- end
78
+ start_root_parent
64
79
  end
65
80
 
66
- $timetravel_root ||= $$
81
+ @timetravel_root ||= $$
82
+ @snap_tree ||= {
83
+ $$.to_s => {
84
+ "file" => target.eval('__FILE__'),
85
+ "line" => target.eval('__LINE__'),
86
+ }
87
+ }
67
88
 
68
89
  parent_pid = $$
69
90
  child_pid = fork
91
+
70
92
  if child_pid
71
- dlog("I am parent #{parent_pid}: I have a child pid #{child_pid}")
72
93
 
73
- # Method 3: Child suspends themselves, parent adds them to list
74
- @previous_pid ||= []
75
- @previous_pid.push child_pid
94
+ dlog("I am parent #{parent_pid}: I have a child pid #{child_pid}")
95
+ enter_suspended_animation
76
96
 
77
- # Perform operation
78
- yield
97
+ # Perform child operation
98
+ child.()
79
99
 
80
100
  else
101
+
81
102
  child_pid = $$
82
103
  dlog("I am child #{child_pid}: I have a parent pid #{parent_pid}")
83
- enter_suspended_animation
104
+
105
+ @snap_tree[child_pid.to_s] = {
106
+ "previous" => parent_pid,
107
+ "file" => target.eval('__FILE__'),
108
+ "line" => target.eval('__LINE__'),
109
+ }
110
+
111
+ # Perform parent operation
112
+ parent.()
113
+
84
114
  end
85
115
  end
86
116
 
87
- def snapshot_list
88
- @previous_pid && @previous_pid.join(" ")
117
+ def snapshot_list(target, indent = "", node = @timetravel_root.to_s)
118
+ # @snap_tree && @snap_tree.keys.join(" ")
119
+ return unless node && node != ""
120
+
121
+ # This shouldn't be here
122
+ @snap_tree[$$.to_s]["file"] = target.eval('__FILE__')
123
+ @snap_tree[$$.to_s]["line"] = target.eval('__LINE__')
124
+
125
+ out = "#{indent}#{node} #{@snap_tree[node]["file"]} #{@snap_tree[node]["line"]} #{ node == $$.to_s ? '***' : ''}\n"
126
+ @snap_tree.keys.select { |n|
127
+ @snap_tree[n]["previous"] == node.to_i
128
+ }.each do |n|
129
+ out += snapshot_list(target, indent + " ", n)
130
+ end
131
+ out
89
132
  end
90
133
 
91
- def restore_snapshot(target_pid = nil, count = nil)
92
- dlog("Thinking about time travel...");
134
+ def restore_snapshot(target, target_pid = nil, count = 1)
135
+ dlog("Thinking about time travel... $$");
93
136
 
94
- if target_pid.nil? && @previous_pid && ! @previous_pid.empty?
95
- count = 1 if count == 0
96
- target_pid = @previous_pid[-count]
137
+ if target_pid.nil? && @snap_tree && ! @snap_tree[$$.to_s].nil?
138
+ count = 1 if count < 1
139
+ target_pid = @snap_tree[$$.to_s]["previous"]
140
+ @snap_tree[$$.to_s]["file"] = target.eval('__FILE__')
141
+ @snap_tree[$$.to_s]["line"] = target.eval('__LINE__')
97
142
  else
98
143
  target_pid = target_pid
99
144
  end
100
145
 
101
146
  if target_pid
102
147
  dlog("ME #{$$}: I found a target pid #{target_pid}! TIME TRAVEL TIME")
148
+
149
+ File.open("/tmp/timetravel_#{$root_parent}.json", 'w') do |f|
150
+ f.puts @snap_tree.to_json
151
+ end
152
+
103
153
  Process.kill 'SIGCONT', target_pid
104
154
  enter_suspended_animation
105
155
  else
106
156
  dlog("I was unable to time travel. Maybe it is a myth.");
157
+ puts "No previous snapshot found."
107
158
  end
108
159
  end
109
160
 
110
161
  def restore_root_snapshot
111
- restore_snapshot($timetravel_root) if $timetravel_root
162
+ restore_snapshot(@timetravel_root) if @timetravel_root
112
163
  end
113
164
 
114
165
  end
@@ -20,11 +20,14 @@ Pry::Commands.create_command "snap", "Create a snapshot that you can later retur
20
20
  end
21
21
  def process
22
22
  if opts.l?
23
- output.puts PryTimetravel.snapshot_list
23
+ output.puts PryTimetravel.snapshot_list(target)
24
24
  else
25
- PryTimetravel.snapshot do
26
- run(args.join(" ")) unless args.empty?
27
- end
25
+ PryTimetravel.snapshot(
26
+ target,
27
+ -> { run(args.join(" ")) unless args.empty? },
28
+ -> { run('whereami') }
29
+ )
30
+ # run('whereami')
28
31
  end
29
32
  end
30
33
  end
@@ -47,10 +50,10 @@ Pry::Commands.create_command "back", "Go back to the most recent snapshot" do
47
50
  end
48
51
  def process
49
52
  if opts.h?
50
- PryTimetravel.restore_root_snapshot
53
+ PryTimetravel.restore_root_snapshot(target)
51
54
  else
52
- count = args.first.to_i
53
- PryTimetravel.restore_snapshot(opts[:p], count)
55
+ target_pid = args.first ? args.first.to_i : opts[:p]
56
+ PryTimetravel.restore_snapshot(target, target_pid)
54
57
  end
55
58
  end
56
59
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'pry-timetravel'
3
- s.version = '0.0.2'
3
+ s.version = '0.0.3'
4
4
  s.summary = 'Timetravel'
5
5
  s.description = 'Allows you to timetravel!'
6
6
  s.homepage = 'https://github.com/awwaiid/pry-timetravel'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pry-timetravel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brock Wilcox
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-20 00:00:00.000000000 Z
11
+ date: 2014-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry