hijack 0.2.0.rc1 → 0.2.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +4 -0
- data/lib/hijack/gdb.rb +37 -19
- data/lib/hijack/payload.rb +1 -1
- data/lib/hijack.rb +1 -1
- data/tasks/gem.rake +6 -7
- data/test/gc.rb +1 -1
- metadata +16 -13
data/README.rdoc
CHANGED
@@ -119,3 +119,7 @@ DRb cannot dump objects to the hijack client for types that are not loaded in th
|
|
119
119
|
isn't loaded in the hijack client.
|
120
120
|
|
121
121
|
To work around this, when hijack connects to a remote process it will inspect all the files required by the process and also attempt to require them itself. This may not work for all object types however so you may still get a warning when an object cannot be dumped.
|
122
|
+
|
123
|
+
== Contributors
|
124
|
+
|
125
|
+
* jugyo (十行) (https://github.com/jugyo)
|
data/lib/hijack/gdb.rb
CHANGED
@@ -6,16 +6,16 @@ module Hijack
|
|
6
6
|
@pid = pid
|
7
7
|
@verbose = Hijack.options[:debug]
|
8
8
|
@exec_path = File.join(Config::CONFIG['bindir'], Config::CONFIG['RUBY_INSTALL_NAME'] + Config::CONFIG['EXEEXT'])
|
9
|
-
|
9
|
+
attach_outside_gc
|
10
10
|
end
|
11
11
|
|
12
12
|
def eval(cmd)
|
13
13
|
call("(void)rb_eval_string(#{cmd.strip.gsub(/"/, '\"').inspect})")
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def quit
|
17
17
|
return unless @gdb
|
18
|
-
|
18
|
+
detach
|
19
19
|
exec('quit')
|
20
20
|
@backtrace = nil
|
21
21
|
@gdb.close
|
@@ -24,35 +24,53 @@ module Hijack
|
|
24
24
|
|
25
25
|
protected
|
26
26
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
def previous_frame_inner_to_this_frame?
|
28
|
+
backtrace.first =~ /previous frame inner to this frame/i
|
29
|
+
end
|
30
|
+
|
31
|
+
def attach_outside_gc
|
32
|
+
@gdb = IO.popen("gdb -q #{@exec_path} #{@pid} 2>&1", 'r+')
|
33
|
+
wait
|
34
|
+
ensure_attached_to_ruby_process
|
35
|
+
attached = false
|
36
|
+
|
37
|
+
3.times do |i|
|
38
|
+
attach unless i == 0
|
39
|
+
|
40
|
+
if previous_frame_inner_to_this_frame? || during_gc?
|
32
41
|
detach
|
33
42
|
sleep 0.1
|
34
43
|
else
|
44
|
+
attached = true
|
35
45
|
break
|
36
46
|
end
|
37
47
|
end
|
38
|
-
|
48
|
+
|
49
|
+
unless attached
|
50
|
+
puts
|
51
|
+
puts "=> Tried 3 times to attach to #{@pid} whilst GC wasn't running but failed."
|
52
|
+
puts "=> This means either the process calls GC.start frequently or its GC runs are slow - try hijacking again."
|
53
|
+
exit 1
|
54
|
+
end
|
55
|
+
|
39
56
|
# TODO: Check for "Unable to attach to process-id 44528: No child processes (10)"
|
40
57
|
ensure_main_thread_not_blocked_by_join
|
41
|
-
set_breakpoint
|
42
|
-
continue
|
43
|
-
delete_breakpoint
|
44
58
|
end
|
45
59
|
|
46
|
-
def
|
47
|
-
|
60
|
+
def during_gc?
|
61
|
+
backtrace.any? { |line| line =~ /garbage_collect/i }
|
48
62
|
end
|
49
|
-
|
50
|
-
def
|
51
|
-
exec("
|
63
|
+
|
64
|
+
def detach
|
65
|
+
exec("detach")
|
52
66
|
end
|
53
|
-
|
67
|
+
|
68
|
+
def attach
|
69
|
+
exec("attach #{@pid}")
|
70
|
+
end
|
71
|
+
|
54
72
|
def ensure_main_thread_not_blocked_by_join
|
55
|
-
if backtrace.any? {|line| line =~ /rb_thread_join/}
|
73
|
+
if backtrace.any? { |line| line =~ /rb_thread_join/ }
|
56
74
|
puts "\n=> Unable to hijack #{@pid} because the main thread is blocked waiting for another thread to join."
|
57
75
|
puts "=> Check that you are using the most recent version of hijack, a newer version may have solved this shortcoming."
|
58
76
|
detach
|
data/lib/hijack/payload.rb
CHANGED
data/lib/hijack.rb
CHANGED
data/tasks/gem.rake
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
require 'rake/gempackagetask'
|
2
2
|
require 'yaml'
|
3
|
-
|
4
|
-
HIJACK_VERSION = '0.1.9'
|
3
|
+
require './lib/hijack'
|
5
4
|
|
6
5
|
task :clean => :clobber_package
|
7
6
|
|
8
7
|
spec = Gem::Specification.new do |s|
|
9
8
|
s.name = 'hijack'
|
10
|
-
s.version =
|
9
|
+
s.version = Hijack.version
|
11
10
|
s.platform = Gem::Platform::RUBY
|
12
11
|
s.summary =
|
13
|
-
s.description = 'Provides an irb session to
|
12
|
+
s.description = 'Provides an irb session to a running ruby process.'
|
14
13
|
s.author = "Ian Leitch"
|
15
|
-
s.email = '
|
14
|
+
s.email = 'port001@gmail.com'
|
16
15
|
s.homepage = 'http://github.com/ileitch/hijack'
|
17
16
|
s.has_rdoc = false
|
18
17
|
s.files = %w(COPYING TODO README.rdoc Rakefile) + Dir.glob("{lib,test,tasks,bin,examples}/**/*")
|
@@ -26,8 +25,8 @@ Rake::GemPackageTask.new(spec) do |p|
|
|
26
25
|
end
|
27
26
|
|
28
27
|
namespace :gem do
|
29
|
-
desc "Update the gemspec
|
30
|
-
task :
|
28
|
+
desc "Update the gemspec"
|
29
|
+
task :spec do
|
31
30
|
File.open("hijack.gemspec", 'w') { |f| f << YAML.dump(spec) }
|
32
31
|
end
|
33
32
|
end
|
data/test/gc.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hijack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 977940575
|
5
|
+
prerelease: true
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 2
|
8
9
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.2.0.
|
10
|
+
- rc2
|
11
|
+
version: 0.2.0.rc2
|
11
12
|
platform: ruby
|
12
13
|
authors:
|
13
14
|
- Ian Leitch
|
@@ -15,11 +16,11 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date:
|
19
|
+
date: 2010-11-26 00:00:00 +11:00
|
19
20
|
default_executable:
|
20
21
|
dependencies: []
|
21
22
|
|
22
|
-
description: Provides an irb session to
|
23
|
+
description: Provides an irb session to a running ruby process.
|
23
24
|
email: port001@gmail.com
|
24
25
|
executables:
|
25
26
|
- hijack
|
@@ -35,9 +36,9 @@ files:
|
|
35
36
|
- lib/hijack/console.rb
|
36
37
|
- lib/hijack/gdb.rb
|
37
38
|
- lib/hijack/helper.rb
|
39
|
+
- lib/hijack/output_receiver.rb
|
38
40
|
- lib/hijack/payload.rb
|
39
41
|
- lib/hijack/workspace.rb
|
40
|
-
- lib/hijack/output_receiver.rb
|
41
42
|
- lib/hijack.rb
|
42
43
|
- test/app.rb
|
43
44
|
- test/gc.rb
|
@@ -55,6 +56,7 @@ rdoc_options: []
|
|
55
56
|
require_paths:
|
56
57
|
- lib
|
57
58
|
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
58
60
|
requirements:
|
59
61
|
- - ">="
|
60
62
|
- !ruby/object:Gem::Version
|
@@ -62,22 +64,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
64
|
segments:
|
63
65
|
- 0
|
64
66
|
version: "0"
|
65
|
-
version:
|
66
67
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
67
69
|
requirements:
|
68
|
-
- - "
|
70
|
+
- - ">"
|
69
71
|
- !ruby/object:Gem::Version
|
70
|
-
hash:
|
72
|
+
hash: 25
|
71
73
|
segments:
|
72
|
-
-
|
73
|
-
|
74
|
-
|
74
|
+
- 1
|
75
|
+
- 3
|
76
|
+
- 1
|
77
|
+
version: 1.3.1
|
75
78
|
requirements: []
|
76
79
|
|
77
80
|
rubyforge_project:
|
78
81
|
rubygems_version: 1.3.7
|
79
82
|
signing_key:
|
80
83
|
specification_version: 3
|
81
|
-
summary: Provides an irb session to
|
84
|
+
summary: Provides an irb session to a running ruby process.
|
82
85
|
test_files: []
|
83
86
|
|