rbtrace 0.4.14 → 0.5.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78fc8aa96b3b20a4663ceaef1253f41443689e85f344a9efecb60c240e85183b
4
- data.tar.gz: 2f2ab561dfe12096dcbe28ff188d07e34af48bbed936f09bbc0dd23309132bea
3
+ metadata.gz: dc6fc7320951955050f41babf4a1effbec1eaac42e9103a0c8b08c69cc2ad090
4
+ data.tar.gz: 105f410c0c78e6f23c3d6617165b7a1c3c9a72976735cfd185481c91acb3bb17
5
5
  SHA512:
6
- metadata.gz: 1710793189ea23b9048c68ff61c1c7f52202b4e7770991e4c049f9b1b069dbbe4fd71f59e2e79a06d34c4c15628073d0498175fcbb64572152c22b9636557a09
7
- data.tar.gz: 315c8c2bc040cf790e4964a93ee9f50b97f9b2b7718f71790e8af36cb2d1fe01d529da06fd6b346747e45fc82b52b2fde6fd62bf9053010e8e93d38f76e575fe
6
+ metadata.gz: a4e42ec27236d32067f52fa3c0ed1a1a3eb518f1f0d4de9c42dcbec787dc62346f39c790ae2b74fcca6835bc1413c3e44216398c8ca46d74d760f0d75a551873
7
+ data.tar.gz: 4602057b9797b58337d2308a195ee1d1e6e9247a7e08bebf40d153bd9c6f4fb1f4871851b514b0fef471cf87df002632b0c75ff6511dc926e58c86be453d8b67
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: Test
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ ruby:
7
+ name: Ruby ${{ matrix.ruby }}
8
+ timeout-minutes: 15
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ os: ["ubuntu-latest"]
13
+ ruby: ["3.2", "3.1", "3.0", "2.7", "2.6"]
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Check out code
17
+ uses: actions/checkout@v3
18
+
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby }}
23
+ bundler-cache: true
24
+
25
+ - name: Tests
26
+ run: ./test.sh
data/CHANGELOG ADDED
@@ -0,0 +1,7 @@
1
+ - 0.5.0 - 02-12-2023
2
+
3
+ - Improved --backtraces implementation
4
+ - Added --shapedump which is useful for lighter weight object shape dumps on Ruby 3.2 and up
5
+ - Move heap dumping to a fork for better performance
6
+ - Use TypedData API which has been supported for a very long time
7
+ - Update CI and fix some small errors
data/ext/extconf.rb CHANGED
@@ -63,11 +63,6 @@ have_func('rb_during_gc', 'ruby.h')
63
63
  have_func('rb_gc_add_event_hook', ['ruby.h', 'node.h'])
64
64
  have_func('rb_postponed_job_register_one', 'ruby.h')
65
65
 
66
- # increase message size on linux
67
- if RUBY_PLATFORM =~ /linux/
68
- $defs.push("-DBUF_SIZE=256")
69
- end
70
-
71
66
  # warnings save lives
72
67
  $CFLAGS << " -Wall "
73
68
 
data/ext/rbtrace.c CHANGED
@@ -79,7 +79,7 @@ timeofday_usec()
79
79
  #define MAX_TRACERS 100 // max method tracers
80
80
  #define MAX_EXPRS 10 // max expressions per tracer
81
81
  #ifndef BUF_SIZE // msgq buffer size
82
- #define BUF_SIZE 120
82
+ #define BUF_SIZE 1024
83
83
  #endif
84
84
 
85
85
  typedef struct {
@@ -876,9 +876,7 @@ eval_inspect(VALUE rb_code) {
876
876
  }
877
877
 
878
878
  static VALUE
879
- rescue_inspect(VALUE arg) {
880
- VALUE exception = rb_errinfo(); /* get last exception */
881
- rb_set_errinfo(Qnil);
879
+ rescue_inspect(VALUE arg, VALUE exception) {
882
880
  return rb_funcall(exception, rb_intern("inspect"), 0);
883
881
  }
884
882
 
@@ -891,7 +889,6 @@ rbtrace__process_event(msgpack_object cmd)
891
889
  static int last_tracer_id = -1; // hax
892
890
  char query[BUF_SIZE];
893
891
 
894
- char code[BUF_SIZE+150];
895
892
  VALUE val = Qnil;
896
893
 
897
894
  msgpack_object_array ary;
@@ -1135,31 +1132,26 @@ send_write(VALUE klass, VALUE val) {
1135
1132
  return Qnil;
1136
1133
  }
1137
1134
 
1135
+ static const rb_data_type_t rbtrace_type = {
1136
+ "RBTrace",
1137
+ {
1138
+ rbtrace_gc_mark,
1139
+ }
1140
+ };
1141
+
1138
1142
  void
1139
1143
  Init_rbtrace()
1140
1144
  {
1141
1145
  rbtrace_module = rb_define_module("RBTrace");
1142
1146
  VALUE output = rb_define_module_under(rbtrace_module, "OUT");
1143
1147
 
1144
- rb_define_singleton_method(output, "write", send_write, 1);
1148
+ rb_const_set(rbtrace_module, rb_intern("BUF_SIZE"), INT2NUM(BUF_SIZE));
1145
1149
 
1146
- rb_eval_string(
1147
- "module RBTrace\n"
1148
- " def self.eval_context\n"
1149
- " @eval_context ||= binding\n"
1150
- " end\n"
1151
-
1152
- " def self.eval_and_inspect(code)\n"
1153
- " t = Thread.new { Thread.current[:output] = eval_context.eval(code).inspect }\n"
1154
- " t.join\n"
1155
- " t[:output]\n"
1156
- " end\n"
1157
- "end\n"
1158
- );
1150
+ rb_define_singleton_method(output, "write", send_write, 1);
1159
1151
 
1160
1152
  // hook into the gc
1161
- gc_hook = Data_Wrap_Struct(rb_cObject, rbtrace_gc_mark, NULL, NULL);
1162
1153
  rb_global_variable(&gc_hook);
1154
+ gc_hook = TypedData_Wrap_Struct(rb_cObject, &rbtrace_type, NULL);
1163
1155
 
1164
1156
  // catch signal telling us to read from the msgq
1165
1157
  #if defined(HAVE_RB_POSTPONED_JOB_REGISTER_ONE)
data/lib/rbtrace/cli.rb CHANGED
@@ -225,6 +225,9 @@ EOS
225
225
  :default => "AUTO",
226
226
  :short => "-h"
227
227
 
228
+ opt :shapesdump,
229
+ "generate a shapes dump for the process in FILENAME",
230
+ :default => "AUTO"
228
231
  end
229
232
 
230
233
  opts = Optimist.with_standard_exception_handling(parser) do
@@ -241,7 +244,7 @@ EOS
241
244
  end
242
245
 
243
246
  unless %w[ fork eval interactive backtrace backtraces slow slowcpu firehose methods config gc memory heapdump].find{ |n| opts[:"#{n}_given"] }
244
- $stderr.puts "Error: --slow, --slowcpu, --gc, --firehose, --methods, --interactive, --backtraces, --backtrace, --memory, --heapdump or --config required."
247
+ $stderr.puts "Error: --slow, --slowcpu, --gc, --firehose, --methods, --interactive, --backtraces, --backtrace, --memory, --heapdump, --shapesdump or --config required."
245
248
  $stderr.puts "Try --help for help."
246
249
  exit(-1)
247
250
  end
@@ -449,7 +452,7 @@ EOS
449
452
 
450
453
  delim = "146621c9d681409aa"
451
454
 
452
- code = "Thread.list.map{|t| t.backtrace[0...#{num}].join(\"#{delim}\")}.join(\"#{delim*2}\")"
455
+ code = "Thread.list.reject { |t| t.name == '__RBTrace__' }.map{ |t| t.backtrace[0...#{num}].join(\"#{delim}\")}.join(\"#{delim*2}\")"
453
456
 
454
457
  if res = tracer.eval(code)
455
458
  tracer.puts res.split(delim).join("\n")
@@ -499,9 +502,47 @@ EOS
499
502
  temp.unlink
500
503
  end
501
504
 
502
- tracer.eval("file = File.open('#{filename}', 'w'); ObjectSpace.dump_all(output: file); file.close")
505
+ tracer.eval(<<-RUBY)
506
+ Thread.new do
507
+ Thread.current.name = '__RBTrace__'
508
+ pid = ::Process.fork do
509
+ file = File.open('#{filename}.tmp', 'w')
510
+ ObjectSpace.dump_all(output: file)
511
+ file.close
512
+ File.rename('#{filename}.tmp', '#{filename}')
513
+ exit!(0)
514
+ end
515
+ Process.waitpid(pid)
516
+ end
517
+ RUBY
503
518
  puts "Heapdump being written to #{filename}"
504
519
 
520
+ elsif opts[:shapesdump_given]
521
+ filename = opts[:shapesdump]
522
+
523
+ if filename == "AUTO"
524
+ require 'tempfile'
525
+ temp = Tempfile.new("dump")
526
+ filename = temp.path
527
+ temp.close
528
+ temp.unlink
529
+ end
530
+
531
+ tracer.eval(<<-RUBY)
532
+ Thread.new do
533
+ Thread.current.name = '__RBTrace__'
534
+ pid = ::Process.fork do
535
+ file = File.open('#{filename}.tmp', 'w')
536
+ ObjectSpace.dump_shapes(output: file)
537
+ file.close
538
+ File.rename('#{filename}.tmp', '#{filename}')
539
+ exit!(0)
540
+ end
541
+ Process.waitpid(pid)
542
+ end
543
+ RUBY
544
+ puts "Shapes dump being written to #{filename}"
545
+
505
546
  elsif opts[:eval_given]
506
547
  if res = tracer.eval(code = opts[:eval])
507
548
  tracer.puts ">> #{code}"
@@ -1,7 +1,3 @@
1
- class String
2
- alias :bytesize :size
3
- end unless ''.respond_to?(:bytesize)
4
-
5
1
  module FFI::LastError
6
2
  Errnos = Errno::constants.map(&Errno.method(:const_get)).inject({}) do |hash, c|
7
3
  hash[ c.const_get(:Errno) ] = c
data/lib/rbtrace/msgq.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'rbtrace'
1
2
  require 'ffi'
2
3
 
3
4
  module MsgQ
@@ -5,7 +6,7 @@ module MsgQ
5
6
  ffi_lib FFI::CURRENT_PROCESS
6
7
 
7
8
  class EventMsg < FFI::Struct
8
- BUF_SIZE = RUBY_PLATFORM =~ /linux/ ? 256 : 120
9
+ BUF_SIZE = RBTrace::BUF_SIZE
9
10
  IPC_NOWAIT = 004000
10
11
 
11
12
  layout :mtype, :long,
@@ -323,7 +323,9 @@ class RBTracer
323
323
  msg = cmd.to_msgpack
324
324
  # A message is null-terminated, but bytesize gives the unterminated
325
325
  # length.
326
- raise ArgumentError, 'command is too long' if msg.bytesize >= MsgQ::EventMsg::BUF_SIZE
326
+ if msg.bytesize >= RbTrace::BUF_SIZE
327
+ raise ArgumentError, "command is too long (#{msg.bytesize}B >= #{MsgQ::EventMsg::BUF_SIZE}B)"
328
+ end
327
329
  MsgQ::EventMsg.send_cmd(@qo, msg)
328
330
  rescue Errno::EINTR
329
331
  retry
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RBTracer
4
- VERSION = '0.4.14'
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/rbtrace.rb ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBTrace
4
+ class << self
5
+ def eval_and_inspect(code)
6
+ t = Thread.new do
7
+ Thread.current.name = '__RBTrace__'
8
+ Thread.current[:output] = eval_context.eval(code).inspect
9
+ end
10
+ t.join
11
+ t[:output]
12
+ end
13
+
14
+ private
15
+
16
+ def eval_context
17
+ @eval_context ||= binding
18
+ end
19
+ end
20
+ end
21
+
22
+ require 'rbtrace.so'
data/rbtrace.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_dependency 'optimist', '>= 3.0.0'
24
24
  s.add_dependency 'msgpack', '>= 0.4.3'
25
25
 
26
- s.add_development_dependency "rake", "~> 10.0"
26
+ s.add_development_dependency "rake"
27
27
 
28
28
  s.license = "MIT"
29
29
  s.summary = 'rbtrace: like strace but for ruby code'
data/server.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'ext/rbtrace'
1
+ require 'rbtrace'
2
2
  require 'tmpdir'
3
3
 
4
4
  class String
data/test.sh CHANGED
@@ -12,7 +12,7 @@ cd ..
12
12
  bundle check
13
13
  export RUBYOPT="-I.:lib"
14
14
 
15
- ruby server.rb &
15
+ bundle exec ruby server.rb &
16
16
  export PID=$!
17
17
 
18
18
  trap cleanup INT TERM
@@ -23,11 +23,11 @@ cleanup() {
23
23
 
24
24
  trace() {
25
25
  echo ------------------------------------------
26
- echo ./bin/rbtrace -p $PID $*
26
+ echo ./bin/rbtrace -p $PID "$@"
27
27
  echo ------------------------------------------
28
- ./bin/rbtrace -p $PID $* &
28
+ bundle exec ./bin/rbtrace -p $PID "$@" &
29
29
  sleep 2
30
- kill $!
30
+ kill $! || true
31
31
  wait $! || true
32
32
  echo
33
33
  }
@@ -37,6 +37,8 @@ trace -m sleep
37
37
  trace -m sleep Dir.chdir Dir.pwd Process.pid "String#gsub" "String#*"
38
38
  trace -m "Kernel#"
39
39
  trace -m "String#gsub(self,@test)" "String#*(self,__source__)" "String#multiply_vowels(self,self.length,num)"
40
+ trace -e 'p(1 + 1)'
41
+ trace -h
40
42
  trace --gc --slow=200
41
43
  trace --gc -m Dir.
42
44
  trace --slow=250
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbtrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.14
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aman Gupta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-03 00:00:00.000000000 Z
11
+ date: 2023-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '0'
69
69
  description: rbtrace shows you method calls happening inside another ruby process
70
70
  in real time.
71
71
  email: aman@tmm1.net
@@ -75,7 +75,9 @@ extensions:
75
75
  - ext/extconf.rb
76
76
  extra_rdoc_files: []
77
77
  files:
78
+ - ".github/workflows/ci.yml"
78
79
  - ".gitignore"
80
+ - CHANGELOG
79
81
  - Gemfile
80
82
  - LICENSE
81
83
  - README.md
@@ -85,6 +87,7 @@ files:
85
87
  - ext/extconf.rb
86
88
  - ext/rbtrace.c
87
89
  - ext/src/msgpack-1.1.0.tar.gz
90
+ - lib/rbtrace.rb
88
91
  - lib/rbtrace/cli.rb
89
92
  - lib/rbtrace/core_ext.rb
90
93
  - lib/rbtrace/interactive/irb.rb
@@ -123,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
126
  - !ruby/object:Gem::Version
124
127
  version: '0'
125
128
  requirements: []
126
- rubygems_version: 3.0.3
129
+ rubygems_version: 3.4.19
127
130
  signing_key:
128
131
  specification_version: 4
129
132
  summary: 'rbtrace: like strace but for ruby code'