rb-trace 0.2

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/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.org>
2
+ All rights reserved.
3
+ *
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions
6
+ are met:
7
+ 1. Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+ *
13
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
+ SUCH DAMAGE.
data/NEWS ADDED
@@ -0,0 +1,2 @@
1
+ September 12 2010 (0.2)
2
+ First release on gemcutter
data/Rakefile ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env rake
2
+ # -*- Ruby -*-
3
+ require 'rubygems'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/testtask'
6
+
7
+ SO_NAME = 'trace.so'
8
+
9
+ PACKAGE_VERSION = open('ext/trace.c') do |f|
10
+ f.grep(/^#define TRACE_VERSION/).first[/"(.+)"/,1]
11
+ end
12
+
13
+ EXT_FILES = FileList[%w(ext/*.c ext/*.h)]
14
+ LIB_FILES = FileList['lib/*.rb']
15
+ TEST_FILES = FileList['test/**/*.rb']
16
+ COMMON_FILES = FileList[%w(Rakefile NEWS LICENSE)]
17
+ ALL_FILES = COMMON_FILES + TEST_FILES + EXT_FILES + LIB_FILES
18
+
19
+ desc "Create a GNU-style ChangeLog via git2cl"
20
+ task :ChangeLog do
21
+ system("git log --pretty --numstat --summary | git2cl > ChangeLog")
22
+ end
23
+
24
+ desc 'Test units - the smaller tests'
25
+ task :'test:unit' => [:ext] do |t|
26
+ Rake::TestTask.new(:'test:unit') do |t|
27
+ t.test_files = FileList['test/unit/**/*.rb']
28
+ # t.pattern = 'test/**/*test-*.rb' # instead of above
29
+ t.verbose = true
30
+ end
31
+ end
32
+
33
+ desc "Create the core ruby-debug shared library extension"
34
+ task :ext do
35
+ Dir.chdir('ext') do
36
+ system("#{Gem.ruby} extconf.rb && make")
37
+ end
38
+ end
39
+
40
+ desc 'Remove built files'
41
+ task :clean do
42
+ cd 'ext' do
43
+ if File.exist?('Makefile')
44
+ sh 'make clean'
45
+ rm 'Makefile'
46
+ end
47
+ derived_files = Dir.glob('.o') + Dir.glob('*.so')
48
+ rm derived_files unless derived_files.empty?
49
+ end
50
+ end
51
+
52
+ desc 'Test everything - unit tests for now.'
53
+ task :test do
54
+ exceptions = ['test:unit'].collect do |task|
55
+ begin
56
+ Rake::Task[task].invoke
57
+ nil
58
+ rescue => e
59
+ e
60
+ end
61
+ end.compact
62
+ end
63
+
64
+ desc "Test everything - same as test."
65
+ task :check => :test
66
+ task :default => [:test]
67
+
68
+ # Base GEM Specification
69
+ spec = Gem::Specification.new do |spec|
70
+ spec.name = "rb-trace"
71
+
72
+ spec.homepage = "http://github.com/rocky/rb-trace/tree/master"
73
+ spec.summary = "Trace hook extensions"
74
+ spec.description = <<-EOF
75
+
76
+ rb-trace adds a trace_hook object, translates hooks bitmasks to sets
77
+ and vice versa, and extends set_trace_func to ignore frames or
78
+ functions.
79
+ EOF
80
+
81
+ spec.version = PACKAGE_VERSION
82
+ spec.extensions = ['ext/extconf.rb']
83
+
84
+ spec.author = "R. Bernstein"
85
+ spec.email = "rockyb@rubyforge.org"
86
+ spec.platform = Gem::Platform::RUBY
87
+ spec.files = ALL_FILES.to_a
88
+ spec.add_dependency('rb-threadframe', '>= 0.32')
89
+
90
+ spec.required_ruby_version = '>= 1.9.2'
91
+ spec.date = Time.now
92
+ # spec.rubyforge_project = 'rocky-hacks'
93
+
94
+ # rdoc
95
+ spec.has_rdoc = true
96
+ # spec.extra_rdoc_files = ['README', 'threadframe.rd']
97
+ end
98
+
99
+ # Rake task to build the default package
100
+ Rake::GemPackageTask.new(spec) do |pkg|
101
+ pkg.need_tar = true
102
+ end
103
+
104
+ def install(spec, *opts)
105
+ args = ['gem', 'install', "pkg/#{spec.name}-#{spec.version}.gem"] + opts
106
+ system(*args)
107
+ end
108
+
109
+ desc 'Install locally'
110
+ task :install => :package do
111
+ Dir.chdir(File::dirname(__FILE__)) do
112
+ # ri and rdoc take lots of time
113
+ install(spec, '--no-ri', '--no-rdoc')
114
+ end
115
+ end
116
+
117
+ task :install_full => :package do
118
+ Dir.chdir(File::dirname(__FILE__)) do
119
+ install(spec)
120
+ end
121
+ end
data/ext/extconf.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "mkmf"
2
+
3
+ config_file = File.join(File.dirname(__FILE__), 'config_options')
4
+ load config_file if File.exist?(config_file)
5
+
6
+ # Temporary: to turn off optimization
7
+ # $CFLAGS='-fno-strict-aliasing -g -fPIC'
8
+ create_makefile("trace")
@@ -0,0 +1,24 @@
1
+ /**********************************************************************
2
+
3
+ thread_pthread.h -
4
+
5
+ $Author$
6
+
7
+ Copyright (C) 2004-2007 Koichi Sasada
8
+
9
+ **********************************************************************/
10
+
11
+ #ifndef RUBY_THREAD_PTHREAD_H
12
+ #define RUBY_THREAD_PTHREAD_H
13
+
14
+ #include <pthread.h>
15
+ typedef pthread_t rb_thread_id_t;
16
+ typedef pthread_mutex_t rb_thread_lock_t;
17
+ typedef pthread_cond_t rb_thread_cond_t;
18
+
19
+ typedef struct native_thread_data_struct {
20
+ void *signal_thread_list;
21
+ pthread_cond_t sleep_cond;
22
+ } native_thread_data_t;
23
+
24
+ #endif /* RUBY_THREAD_PTHREAD_H */
data/ext/trace.c ADDED
@@ -0,0 +1,160 @@
1
+ #include "vm_core_mini.h" /* Pulls in ruby.h */
2
+
3
+ /* What release we got? */
4
+ #define TRACE_VERSION "0.2"
5
+
6
+ extern VALUE rb_cRubyVM; /* RubyVM class */
7
+ extern rb_vm_t *ruby_current_vm;
8
+ extern VALUE rb_obj_is_proc(VALUE proc);
9
+
10
+ VALUE rb_cTraceHook; /* TraceHook class */
11
+ VALUE rb_eTraceHookError; /* Exception raised by TraceHook class */
12
+
13
+ /* Extra information we need to save about a hook.
14
+ FIXME: For now we will work only with vm hooks. When this
15
+ extends to thread hooks, we will need to use this.
16
+ */
17
+ typedef struct
18
+ {
19
+ rb_thread_t *th; /* If NULL, hook is in vm. Otherwise, this
20
+ is the thread the hook belongs to. */
21
+ rb_event_hook_t *hook;
22
+ } hook_info_t;
23
+
24
+ static int is_hook_member(rb_event_hook_t *check_hook, rb_event_hook_t *hook);
25
+
26
+ static void
27
+ check_hook_valid(rb_event_hook_t *check_hook)
28
+ {
29
+ /* FIXME: in the future use check_hook to find the hook head. */
30
+ rb_event_hook_t *hook_head = GET_VM()->event_hooks;
31
+
32
+ if (!is_hook_member(check_hook, hook_head))
33
+ rb_raise(rb_eTraceHookError, "hook not found");
34
+ }
35
+
36
+ /* Return an Array of vm event hooks found from hook. */
37
+ VALUE
38
+ get_trace_hooks(rb_event_hook_t *hook)
39
+ {
40
+ VALUE ary;
41
+ for (ary = rb_ary_new(); hook; hook = hook->next)
42
+ rb_ary_push(ary, Data_Wrap_Struct(rb_cTraceHook, NULL, NULL, hook));
43
+ return ary;
44
+ }
45
+
46
+ /* Return 1 if check_hook is found in the list of hooks pointed to by
47
+ 'hook', or 0 if not found. */
48
+ static int
49
+ is_hook_member(rb_event_hook_t *check_hook, rb_event_hook_t *hook)
50
+ {
51
+ for (; hook; hook = hook->next) if (check_hook == hook) return 1;
52
+ return 0; /* Not found */
53
+ }
54
+
55
+ /* Return an Array of VM event hooks objects. */
56
+ VALUE
57
+ trace_hook_s_trace_hooks()
58
+ {
59
+ return get_trace_hooks(GET_VM()->event_hooks);
60
+ }
61
+
62
+ /*
63
+ Return the event mask value for a given hook. If no hook, then return nil.
64
+ */
65
+ static VALUE
66
+ trace_hook_event_mask(VALUE klass)
67
+ {
68
+ rb_event_hook_t *hook;
69
+ Data_Get_Struct(klass, rb_event_hook_t, hook);
70
+ if (!hook) return Qnil;
71
+ check_hook_valid(hook);
72
+ return INT2FIX(hook->flag);
73
+ }
74
+
75
+ /* Set a new mask value for given hook and return the old mask
76
+ value. Can raise an error if there is no hook installed. */
77
+ static VALUE
78
+ trace_hook_event_mask_set(VALUE klass, VALUE maskval)
79
+ {
80
+ rb_event_hook_t *hook;
81
+ rb_event_flag_t flag;
82
+ Data_Get_Struct(klass, rb_event_hook_t, hook);
83
+ if (!hook)
84
+ rb_raise(rb_eTraceHookError, "No hook installed");
85
+ if (!FIXNUM_P(maskval)) {
86
+ rb_raise(rb_eTypeError, "integer argument expected");
87
+ }
88
+ check_hook_valid(hook);
89
+ flag = hook->flag;
90
+ hook->flag = FIX2INT(maskval);
91
+ return INT2FIX(flag);
92
+ }
93
+
94
+ /*
95
+ Return the event mask value for a given hook. If no hook, then return nil.
96
+ */
97
+ static VALUE
98
+ trace_hook_proc(VALUE klass)
99
+ {
100
+ rb_event_hook_t *hook;
101
+ Data_Get_Struct(klass, rb_event_hook_t, hook);
102
+ if (!hook) return Qnil;
103
+ check_hook_valid(hook);
104
+ return hook->data;
105
+ }
106
+
107
+ /*
108
+ Return the event mask value for a given hook. If no hook, then return nil.
109
+ */
110
+ static VALUE
111
+ trace_hook_proc_set(VALUE klass, VALUE trace_proc)
112
+ {
113
+ rb_event_hook_t *hook;
114
+ if (!rb_obj_is_proc(trace_proc)) {
115
+ rb_raise(rb_eTypeError, "trace_func needs to be Proc");
116
+ }
117
+
118
+ Data_Get_Struct(klass, rb_event_hook_t, hook);
119
+ if (!hook) return Qnil;
120
+ check_hook_valid(hook);
121
+ hook->data = trace_proc;
122
+ return trace_proc;
123
+ }
124
+
125
+ /*
126
+ Return true if hook is still valid or is nil), false otherwise.
127
+ */
128
+ static VALUE
129
+ trace_hook_valid(VALUE klass)
130
+ {
131
+ rb_event_hook_t *hook;
132
+ Data_Get_Struct(klass, rb_event_hook_t, hook);
133
+ /* FIXME in the future we will need to extract whether this hook is
134
+ part of a thread or from the vm.
135
+ */
136
+ return is_hook_member(hook, GET_VM()->event_hooks) ? Qtrue : Qfalse;
137
+ }
138
+
139
+ void
140
+ Init_trace(void)
141
+ {
142
+ rb_eTraceHookError = rb_define_class_under(rb_cRubyVM, "TraceHookError",
143
+ rb_eStandardError);
144
+ rb_cTraceHook = rb_define_class_under(rb_cRubyVM, "TraceHook",
145
+ rb_cObject);
146
+
147
+ rb_define_singleton_method(rb_cTraceHook, "trace_hooks",
148
+ trace_hook_s_trace_hooks, 0);
149
+
150
+ rb_define_method(rb_cTraceHook, "event_mask",
151
+ trace_hook_event_mask, 0);
152
+ rb_define_method(rb_cTraceHook, "event_mask=",
153
+ trace_hook_event_mask_set, 1);
154
+ rb_define_method(rb_cTraceHook, "proc",
155
+ trace_hook_proc, 0);
156
+ rb_define_method(rb_cTraceHook, "proc=",
157
+ trace_hook_proc_set, 1);
158
+ rb_define_method(rb_cTraceHook, "valid?",
159
+ trace_hook_valid, 0);
160
+ }
@@ -0,0 +1,133 @@
1
+ /* Headers Exposing a little more of the 1.9 runtime and some
2
+ method prototypes for extensions to the Thread class.
3
+ */
4
+ #include <ruby.h>
5
+ #include <signal.h>
6
+ #include "thread_pthread.h"
7
+
8
+ /* From vm_core.h: */
9
+
10
+ #define GET_VM() ruby_current_vm
11
+ #define GET_THREAD() ruby_current_thread
12
+
13
+ #if 1
14
+ #define GetCoreDataFromValue(obj, type, ptr) do { \
15
+ ptr = (type*)DATA_PTR(obj); \
16
+ } while (0)
17
+ #else
18
+ #define GetCoreDataFromValue(obj, type, ptr) Data_Get_Struct(obj, type, ptr)
19
+ #endif
20
+ #if 1
21
+ #define GetCoreDataFromValue(obj, type, ptr) do { \
22
+ ptr = (type*)DATA_PTR(obj); \
23
+ } while (0)
24
+ #else
25
+ #define GetCoreDataFromValue(obj, type, ptr) Data_Get_Struct(obj, type, ptr)
26
+ #endif
27
+
28
+ /* Opaque types (for now at least) */
29
+ typedef struct rb_iseq_struct rb_iseq_t;
30
+ typedef struct rb_method_entry_struct rb_method_entry_t;
31
+ typedef struct rb_proc_struct rb_proc_t;
32
+
33
+ typedef struct {
34
+ VALUE *pc; /* cfp[0] */
35
+ VALUE *sp; /* cfp[1] */
36
+ VALUE *bp; /* cfp[2] */
37
+ rb_iseq_t *iseq; /* cfp[3] */
38
+ VALUE flag; /* cfp[4] */
39
+ VALUE self; /* cfp[5] / block[0] */
40
+ VALUE *lfp; /* cfp[6] / block[1] */
41
+ VALUE *dfp; /* cfp[7] / block[2] */
42
+ rb_iseq_t *block_iseq; /* cfp[8] / block[3] */
43
+ VALUE proc; /* cfp[9] / block[4] */
44
+ const rb_method_entry_t *me;/* cfp[10] */
45
+ } rb_control_frame_t;
46
+
47
+ enum ruby_special_exceptions {
48
+ ruby_error_reenter,
49
+ ruby_error_nomemory,
50
+ ruby_error_sysstack,
51
+ ruby_special_error_count
52
+ };
53
+
54
+ #define GetThreadPtr(obj, ptr) \
55
+ GetCoreDataFromValue(obj, rb_thread_t, ptr)
56
+
57
+ #define GetProcPtr(obj, ptr) \
58
+ GetCoreDataFromValue(obj, rb_proc_t, ptr)
59
+
60
+ #ifndef NSIG
61
+ # define NSIG (_SIGMAX + 1) /* For QNX */
62
+ #endif
63
+
64
+ #define RUBY_NSIG NSIG
65
+ typedef struct rb_vm_struct {
66
+ VALUE self;
67
+
68
+ rb_thread_lock_t global_vm_lock;
69
+
70
+ struct rb_thread_struct *main_thread;
71
+ struct rb_thread_struct *running_thread;
72
+
73
+ st_table *living_threads;
74
+ VALUE thgroup_default;
75
+
76
+ int running;
77
+ int thread_abort_on_exception;
78
+ unsigned long trace_flag;
79
+ volatile int sleeper;
80
+
81
+ /* object management */
82
+ VALUE mark_object_ary;
83
+
84
+ VALUE special_exceptions[ruby_special_error_count];
85
+
86
+ /* load */
87
+ VALUE top_self;
88
+ VALUE load_path;
89
+ VALUE loaded_features;
90
+ struct st_table *loading_table;
91
+
92
+ /* signal */
93
+ struct {
94
+ VALUE cmd;
95
+ int safe;
96
+ } trap_list[RUBY_NSIG];
97
+
98
+ /* hook */
99
+ rb_event_hook_t *event_hooks;
100
+
101
+ int src_encoding_index;
102
+
103
+ VALUE verbose, debug, progname;
104
+ VALUE coverages;
105
+
106
+ #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
107
+ struct rb_objspace *objspace;
108
+ #endif
109
+ } rb_vm_t;
110
+
111
+ typedef struct rb_thread_struct
112
+ {
113
+ VALUE self;
114
+ rb_vm_t *vm;
115
+
116
+ /* execution information */
117
+ VALUE *stack; /* must free, must mark. rb: seems to be nil. */
118
+ unsigned long stack_size; /* Number of stack (or rb_control_frame_t) entries */
119
+ rb_control_frame_t *cfp;
120
+
121
+ int safe_level;
122
+ int raised_flag;
123
+ VALUE last_status; /* $? */
124
+
125
+ /* passing state */
126
+ int state;
127
+
128
+ /* Lot's of other stuff ... */
129
+ } rb_thread_t;
130
+
131
+ extern rb_thread_t *ruby_current_thread;
132
+
133
+
@@ -0,0 +1,172 @@
1
+ module Trace
2
+
3
+ class EventBuffer
4
+ EventStruct = Struct.new(:event, :arg, :type, :thread, :method,
5
+ :source_container, :source_location,
6
+ :iseq, :pc_offset) unless defined?(EventStruct)
7
+ attr_reader :buf
8
+ attr_accessor :marks # User position mark into buffer. If buffer is limited,
9
+ attr_reader :maxsize # Maximum size of buffer or nil if unlimited.
10
+ attr_reader :size # size of buffer
11
+ # then marks will drop out as they disappear from the buffer
12
+ def initialize(maxsize=nil)
13
+ @maxsize = maxsize
14
+ reset
15
+ end
16
+
17
+ def reset
18
+ @buf = []
19
+ @marks = []
20
+ @pos = -1
21
+ @size = 0
22
+ end
23
+
24
+ # Add a new event dropping off old events if that was declared
25
+ # marks are also dropped if buffer has a limit.
26
+ def append(event, frame, arg)
27
+ if 'c-return' == event
28
+ arg = frame.sp(2)
29
+ elsif 'return' == event
30
+ arg = frame.sp(1)
31
+ end
32
+
33
+ iseq = frame.iseq
34
+ item = EventStruct.new(event, arg, frame.type, frame.thread, frame.method,
35
+ frame.source_container, frame.source_location,
36
+ iseq, iseq ? frame.pc_offset : nil)
37
+ @pos = self.succ_pos
38
+ @marks.shift if @marks[0] == @pos
39
+ @buf[@pos] = item
40
+ @size += 1 unless @maxsize && @size == @maxsize
41
+ end
42
+
43
+ # Add mark for the current event buffer position.
44
+ def add_mark
45
+ @marks << @pos
46
+ end
47
+
48
+ # Like add mark, but do only if the last marked position has
49
+ # changed
50
+ def add_mark_nodup
51
+ @marks << @pos unless @marks[-1] == @pos
52
+ end
53
+
54
+ def each(from=nil, to=nil)
55
+ from = self.succ_pos unless from
56
+ to = @pos unless to
57
+ if from <= to
58
+ from.upto(to).each do |pos|
59
+ yield @buf[pos]
60
+ end
61
+ else
62
+ from.upto(@size-1).each do |pos|
63
+ yield @buf[pos]
64
+ end
65
+ 0.upto(@pos).each do |pos|
66
+ yield @buf[pos]
67
+ end
68
+ end
69
+ end
70
+
71
+ def each_with_index(from=nil, to=nil)
72
+ from = succ_pos unless from
73
+ to = @pos unless to
74
+ if from <= to
75
+ from.upto(to).each do |pos|
76
+ yield [@buf[pos], pos]
77
+ end
78
+ else
79
+ from.upto(@size-1).each do |pos|
80
+ yield [@buf[pos], pos]
81
+ end
82
+ 0.upto(@pos).each do |pos|
83
+ yield [@buf[pos], pos]
84
+ end
85
+ end
86
+ end
87
+
88
+ def format_entry(item, long_format=true)
89
+ # require 'rbdbgr'; Debugger.debug
90
+ container =
91
+ if item.source_container[0] == 'file'
92
+ item.source_container[1].inspect
93
+ else
94
+ item.source_container.inspect
95
+ end
96
+
97
+ location =
98
+ if 1 == item.source_location.size
99
+ item.source_location[0].inspect
100
+ else
101
+ item.source_location.inspect
102
+ end
103
+
104
+ mess = "#{item.event} #{item.type} #{item.method} " +
105
+ "#{container} #{location}"
106
+ if long_format && item.iseq
107
+ mess += "\n\t" + "VM offset #{item.pc_offset} of #{item.iseq.name}"
108
+ end
109
+ mess
110
+ end
111
+
112
+ # Return the next event buffer position taking into account
113
+ # that we may have a fixed-sized buffer ring.
114
+ def succ_pos(inc=1)
115
+ pos = @pos + inc
116
+ @maxsize ? pos % @maxsize : pos
117
+ end
118
+
119
+ # Return the next event buffer position taking into account
120
+ # that we may have a fixed-sized buffer ring.
121
+ def pred_pos(dec=1)
122
+ pos = @pos - dec
123
+ @maxsize ? pos % @maxsize : pos
124
+ end
125
+
126
+ # Return the adjusted zeroth position in @buf.
127
+ def zero_pos
128
+ if !@maxsize || @buf.size < @maxsize
129
+ 0
130
+ else
131
+ self.succ_pos
132
+ end
133
+ end
134
+
135
+ end # EventBuffer
136
+ end # Trace
137
+
138
+ if __FILE__ == $0
139
+ def event_processor(event, frame, arg=nil)
140
+ begin
141
+ @eventbuf.append(event, frame, arg)
142
+ rescue
143
+ p $!
144
+ end
145
+ end
146
+ def dump_all
147
+ puts '-' * 40
148
+ @eventbuf.each do |e|
149
+ puts @eventbuf.format_entry(e) if e
150
+ end
151
+ end
152
+
153
+ require_relative 'trace'
154
+ @eventbuf = Trace::EventBuffer.new(5)
155
+ p @eventbuf.zero_pos
156
+ dump_all
157
+
158
+ trace_filter = Trace::Filter.new
159
+ trace_func = method(:event_processor).to_proc
160
+ trace_filter << trace_func
161
+ trace_filter.set_trace_func(trace_func)
162
+ z=5
163
+ z.times do |i|
164
+ x = i
165
+ y = x+2
166
+ end
167
+ trace_filter.set_trace_func(nil)
168
+ p @eventbuf.buf[@eventbuf.zero_pos]
169
+ dump_all
170
+ @eventbuf.reset
171
+ dump_all
172
+ end
data/lib/trace.rb ADDED
@@ -0,0 +1,3 @@
1
+ require_relative 'trace_mod'
2
+ require_relative 'tracefilter'
3
+ require_relative 'eventbuffer'