stacktrace 1.0.0 → 1.0.1
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/.autotest +2 -2
- data/History.txt +4 -0
- data/Manifest.txt +0 -2
- data/README.txt +5 -3
- data/Rakefile +1 -11
- data/lib/stacktrace.rb +3 -1
- data/test/test_stacktrace.rb +12 -60
- metadata +18 -7
- data/ext/stacktrace/stacktrace.c +0 -153
- data/lib/stackframe.rb +0 -18
data/.autotest
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
+
|
2
3
|
require 'autotest/restart'
|
3
4
|
|
5
|
+
|
4
6
|
Autotest.add_hook :initialize do |at|
|
5
7
|
at.add_mapping(/.*\.c/) do |f, _|
|
6
8
|
at.files_matching(/test_.*rb$/)
|
7
9
|
end
|
8
|
-
at.add_exception(%r{^\./Gemfile.lock})
|
9
|
-
at.add_exception("lib/stacktrace/stacktrace.bundle")
|
10
10
|
end
|
11
11
|
|
12
12
|
Autotest.add_hook :run_command do |at|
|
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
@@ -19,11 +19,13 @@ In a simple bench it is about 3 times faster than caller due to reduced informat
|
|
19
19
|
|
20
20
|
== REQUIREMENTS:
|
21
21
|
|
22
|
-
* Ruby 1.9.3
|
22
|
+
* Ruby 1.9.3
|
23
23
|
|
24
|
-
==
|
24
|
+
== INSTALL:
|
25
|
+
|
26
|
+
- TODO
|
25
27
|
|
26
|
-
|
28
|
+
== DEVELOPERS:
|
27
29
|
|
28
30
|
After checking out the source, run:
|
29
31
|
|
data/Rakefile
CHANGED
@@ -10,18 +10,13 @@ require 'rake/extensiontask'
|
|
10
10
|
# Hoe.plugin :racc
|
11
11
|
# Hoe.plugin :rcov
|
12
12
|
# Hoe.plugin :rubyforge
|
13
|
-
VERSION = "1.0.0"
|
14
|
-
spec = Gem::Specification.new do |s|
|
15
|
-
s.name = "stacktrace"
|
16
|
-
s.platform = Gem::Platform::RUBY
|
17
|
-
s.extensions = FileList["ext/**/extconf.rb"]
|
18
|
-
end
|
19
13
|
|
20
14
|
Hoe.spec 'stacktrace' do
|
21
15
|
developer('Sam Saffron', 'sam.saffron@gmail.com')
|
22
16
|
|
23
17
|
self.rubyforge_name = 'stacktrace' # if different than 'stacktrace'
|
24
18
|
self.extra_dev_deps << ['rake-compiler', '>=0']
|
19
|
+
self.extra_deps << ['ruby_core_source', '>=0']
|
25
20
|
self.spec_extras = {:extensions => ["ext/stacktrace/extconf.rb"]}
|
26
21
|
|
27
22
|
Rake::ExtensionTask.new('stacktrace', spec) do |ext|
|
@@ -31,9 +26,4 @@ end
|
|
31
26
|
|
32
27
|
Rake::Task[:test].prerequisites << :compile
|
33
28
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
29
|
# vim: syntax=ruby
|
data/lib/stacktrace.rb
CHANGED
data/test/test_stacktrace.rb
CHANGED
@@ -21,74 +21,26 @@ class TestStacktrace < Test::Unit::TestCase
|
|
21
21
|
|
22
22
|
def test_singleton_stacktrace
|
23
23
|
frame = TestStacktrace.test_singleton[0]
|
24
|
-
assert_equal frame
|
25
|
-
assert_equal frame
|
24
|
+
assert_equal frame[:klass], TestStacktrace.metaclass
|
25
|
+
assert_equal frame[:method], "test_singleton"
|
26
26
|
end
|
27
27
|
|
28
28
|
def test_thread_stacktrace
|
29
29
|
frame = Thread.current.stacktrace[0]
|
30
|
-
assert_equal frame
|
31
|
-
assert_equal frame
|
30
|
+
assert_equal frame[:klass], TestStacktrace
|
31
|
+
assert_equal frame[:method], "test_thread_stacktrace"
|
32
32
|
end
|
33
33
|
|
34
34
|
def test_c_func
|
35
|
-
|
36
|
-
[1].map{frame = stacktrace[1]}
|
37
|
-
|
38
|
-
assert_equal frame.method, "map"
|
39
|
-
assert_equal frame.klass, Array
|
35
|
+
p [1].map{stacktrace[0]}
|
40
36
|
end
|
41
37
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
assert_equal __LINE__ - 1, line
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_skipping
|
53
|
-
assert_equal stacktrace(1)[0], stacktrace[(1..-1)][0]
|
54
|
-
end
|
55
|
-
|
56
|
-
def test_simple_range
|
57
|
-
assert_equal stacktrace[1..2], stacktrace(1,2)
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_invalid_range
|
61
|
-
assert_equal stacktrace(1,-10000), []
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_negative_start
|
65
|
-
assert_equal stacktrace(-1), [stacktrace[-1]]
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_same_length_as_caller
|
69
|
-
# caller skips 1 by default
|
70
|
-
caller_length = caller(0).length
|
71
|
-
stack_length = stacktrace.length
|
72
|
-
assert_equal caller_length, stack_length
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_filter_stack
|
76
|
-
frame = stacktrace(0, 0, StackFrame::Flags::METHOD)[0]
|
77
|
-
|
78
|
-
assert_equal nil, frame.klass
|
79
|
-
assert_equal nil, frame.line_number
|
80
|
-
assert_equal nil, frame.filename
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
#stacktrace has similar perf
|
85
|
-
def test_demo_bench
|
86
|
-
return
|
87
|
-
Benchmark.bm(7) do |b|
|
88
|
-
b.report("caller: ") { 100000.times { caller } }
|
89
|
-
b.report("stacktrace: ") { 100000.times { stacktrace } }
|
90
|
-
b.report("stacktrace: ") { 100000.times { stacktrace(0,-1, StackFrame::Flags::METHOD | StackFrame::Flags::KLASS) } }
|
91
|
-
end
|
92
|
-
end
|
38
|
+
# stacktrace is MUCH faster
|
39
|
+
#def test_demo_bench
|
40
|
+
# Benchmark.bm(7) do |b|
|
41
|
+
# b.report("caller: ") { 100000.times { caller } }
|
42
|
+
# b.report("stacktrace: ") { 100000.times { stacktrace } }
|
43
|
+
# end
|
44
|
+
#end
|
93
45
|
|
94
46
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stacktrace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ruby_core_source
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: rdoc
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -79,9 +95,7 @@ files:
|
|
79
95
|
- Rakefile
|
80
96
|
- bin/stacktrace
|
81
97
|
- lib/stacktrace.rb
|
82
|
-
- lib/stackframe.rb
|
83
98
|
- test/test_stacktrace.rb
|
84
|
-
- ext/stacktrace/stacktrace.c
|
85
99
|
- ext/stacktrace/extconf.rb
|
86
100
|
- .gemtest
|
87
101
|
homepage: https://github.com/SamSaffron/stacktrace
|
@@ -98,9 +112,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
112
|
- - ! '>='
|
99
113
|
- !ruby/object:Gem::Version
|
100
114
|
version: '0'
|
101
|
-
segments:
|
102
|
-
- 0
|
103
|
-
hash: -3361579644017678061
|
104
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
116
|
none: false
|
106
117
|
requirements:
|
data/ext/stacktrace/stacktrace.c
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
// much of this is based off reading MRI source code
|
2
|
-
|
3
|
-
#include <ruby.h>
|
4
|
-
#include <vm_core.h>
|
5
|
-
#include <iseq.h>
|
6
|
-
#ifdef RUBY193
|
7
|
-
#define ruby_current_thread ((rb_thread_t *)RTYPEDDATA_DATA(rb_thread_current()))
|
8
|
-
#endif
|
9
|
-
|
10
|
-
#define ST_F_METHOD 1
|
11
|
-
#define ST_F_KLASS 2
|
12
|
-
#define ST_F_FILENAME 4
|
13
|
-
#define ST_F_LINENUMBER 8
|
14
|
-
#define ST_F_ALL 15
|
15
|
-
|
16
|
-
VALUE c_StackFrame;
|
17
|
-
|
18
|
-
static VALUE stacktrace(int argc, VALUE* argv, rb_thread_t *th)
|
19
|
-
{
|
20
|
-
VALUE ary = rb_ary_new();
|
21
|
-
|
22
|
-
int start = 0;
|
23
|
-
int finish = -1;
|
24
|
-
int stack_size = 0;
|
25
|
-
const rb_control_frame_t *cfp = th->cfp;
|
26
|
-
const rb_control_frame_t *tcfp;
|
27
|
-
const rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);
|
28
|
-
VALUE file = Qnil;
|
29
|
-
int line = 0;
|
30
|
-
rb_iseq_t *iseq = 0;
|
31
|
-
ID id;
|
32
|
-
VALUE frame;
|
33
|
-
extern VALUE ruby_engine_name;
|
34
|
-
int flags = ST_F_ALL;
|
35
|
-
|
36
|
-
if (argc > 0) {
|
37
|
-
start = NUM2INT(argv[0]);
|
38
|
-
}
|
39
|
-
|
40
|
-
if (argc > 1) {
|
41
|
-
finish = NUM2INT(argv[1]);
|
42
|
-
}
|
43
|
-
|
44
|
-
if (argc > 2) {
|
45
|
-
flags = NUM2INT(argv[2]);
|
46
|
-
}
|
47
|
-
|
48
|
-
cfp += 1;
|
49
|
-
limit_cfp -= 2;
|
50
|
-
|
51
|
-
if (finish > 0) {
|
52
|
-
finish--;
|
53
|
-
}
|
54
|
-
|
55
|
-
if (start < 0 || finish < 0) {
|
56
|
-
tcfp = cfp;
|
57
|
-
while (tcfp < limit_cfp)
|
58
|
-
{
|
59
|
-
if (tcfp->iseq != 0 && cfp->pc != 0) {
|
60
|
-
stack_size++;
|
61
|
-
}
|
62
|
-
else if (RUBYVM_CFUNC_FRAME_P(tcfp)) {
|
63
|
-
stack_size++;
|
64
|
-
}
|
65
|
-
tcfp++;
|
66
|
-
}
|
67
|
-
|
68
|
-
if (start < 0) {
|
69
|
-
start = stack_size + start;
|
70
|
-
}
|
71
|
-
if (finish < 0) {
|
72
|
-
finish = stack_size + finish;
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
|
-
// rb_warn("flags: %i", flags & ST_F_KLASS);
|
77
|
-
// rb_warn("test %i %i cfp: %i lcfp %i ss %i", start, finish, cfp, limit_cfp, stack_size);
|
78
|
-
|
79
|
-
while (cfp < limit_cfp) {
|
80
|
-
VALUE hash = 0;
|
81
|
-
if (cfp->iseq != 0 && cfp->pc != 0) {
|
82
|
-
if (start-- > 0) {cfp++; continue;}
|
83
|
-
if (finish-- < 0) break;
|
84
|
-
iseq = cfp->iseq;
|
85
|
-
frame = rb_class_new_instance(0, 0, c_StackFrame);
|
86
|
-
if (iseq->defined_method_id && ((flags & ST_F_KLASS) == ST_F_KLASS)) {
|
87
|
-
rb_iv_set(frame, "@klass", iseq->klass);
|
88
|
-
}
|
89
|
-
if ((flags & ST_F_METHOD) == ST_F_METHOD) {
|
90
|
-
rb_iv_set(frame, "@method", iseq->name);
|
91
|
-
}
|
92
|
-
if ((flags & ST_F_FILENAME) == ST_F_FILENAME) {
|
93
|
-
rb_iv_set(frame, "@filename", iseq->filename);
|
94
|
-
}
|
95
|
-
if ((flags & ST_F_LINENUMBER) == ST_F_LINENUMBER) {
|
96
|
-
line = rb_vm_get_sourceline(cfp);
|
97
|
-
rb_iv_set(frame, "@line_number", INT2FIX(line));
|
98
|
-
}
|
99
|
-
rb_ary_push(ary, frame);
|
100
|
-
}
|
101
|
-
else if (RUBYVM_CFUNC_FRAME_P(cfp)) {
|
102
|
-
if (start-- > 0) {cfp++; continue;}
|
103
|
-
if (finish-- < 0) break;
|
104
|
-
if (NIL_P(file)) file = ruby_engine_name;
|
105
|
-
if (cfp->me->def)
|
106
|
-
id = cfp->me->def->original_id;
|
107
|
-
else
|
108
|
-
id = cfp->me->called_id;
|
109
|
-
if (id != ID_ALLOCATOR) {
|
110
|
-
frame = rb_class_new_instance(0, 0, c_StackFrame);
|
111
|
-
if ((flags & ST_F_KLASS) == ST_F_KLASS) {
|
112
|
-
rb_iv_set(frame, "@klass", cfp->me->klass);
|
113
|
-
}
|
114
|
-
if ((flags & ST_F_METHOD) == ST_F_METHOD) {
|
115
|
-
rb_iv_set(frame, "@method", rb_id2str(id));
|
116
|
-
}
|
117
|
-
rb_ary_push(ary,frame);
|
118
|
-
|
119
|
-
}
|
120
|
-
}
|
121
|
-
cfp += 1;
|
122
|
-
}
|
123
|
-
return ary;
|
124
|
-
}
|
125
|
-
|
126
|
-
static VALUE rb_st_kernel_stacktrace(int argc, VALUE* argv)
|
127
|
-
{
|
128
|
-
return stacktrace(argc, argv, GET_THREAD());
|
129
|
-
}
|
130
|
-
|
131
|
-
static VALUE rb_st_thread_stacktrace(int argc, VALUE* argv, VALUE thval)
|
132
|
-
{
|
133
|
-
rb_thread_t *th = (rb_thread_t *)RTYPEDDATA_DATA(thval);
|
134
|
-
|
135
|
-
switch (th->status) {
|
136
|
-
case THREAD_RUNNABLE:
|
137
|
-
case THREAD_STOPPED:
|
138
|
-
case THREAD_STOPPED_FOREVER:
|
139
|
-
break;
|
140
|
-
case THREAD_TO_KILL:
|
141
|
-
case THREAD_KILLED:
|
142
|
-
return Qnil;
|
143
|
-
}
|
144
|
-
|
145
|
-
return stacktrace(argc, argv, th);
|
146
|
-
}
|
147
|
-
|
148
|
-
void Init_stacktrace()
|
149
|
-
{
|
150
|
-
rb_define_global_function("stacktrace", rb_st_kernel_stacktrace, -1);
|
151
|
-
rb_define_method(rb_cThread, "stacktrace", rb_st_thread_stacktrace, -1);
|
152
|
-
c_StackFrame = rb_eval_string("StackFrame");
|
153
|
-
}
|
data/lib/stackframe.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
class StackFrame
|
2
|
-
module Flags
|
3
|
-
METHOD = 1
|
4
|
-
KLASS = 2
|
5
|
-
FILENAME = 4
|
6
|
-
LINENUMBER = 8
|
7
|
-
ALL = 15
|
8
|
-
end
|
9
|
-
|
10
|
-
attr_accessor :line_number, :method, :klass, :filename
|
11
|
-
|
12
|
-
def ==(other)
|
13
|
-
line_number == other.line_number &&
|
14
|
-
self.method == other.method &&
|
15
|
-
klass == other.klass &&
|
16
|
-
filename == other.filename
|
17
|
-
end
|
18
|
-
end
|