stackprof 0.2.22 → 0.2.24

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: 8e473c6b4408f04dc69f4abd425ab68896b4f705adadd467ded771003eb84da1
4
- data.tar.gz: 5bfaa3c22d7e59271f65136b0237cddc4d1a97edf9650db4caf53c9b36fda55e
3
+ metadata.gz: 90e33127951d53147b6a65704446ec812999df9525d868865029ee1c7450445d
4
+ data.tar.gz: 19a5f104482f355cb1957b71b18b15b9ca9bb981cfcc109688366e53704c5711
5
5
  SHA512:
6
- metadata.gz: eb0ffc8bac6c1c66b13ce67d89bac3fbd1c601754024c3e8455e194a35e58f3c515586aa0ffeee4e30985a6e140ce64724c0960dce8de67d8a3e0f0e912d3898
7
- data.tar.gz: 4cfc9aa211ab10a7b0a0c222e94538311bd91950fa32fc0602e2535468df4c48158219cad2f2f6fee015f94a9b415c3a285406fcc66ab27676a6572492b2d7f9
6
+ metadata.gz: 17610238200852f97afcc730efd9171c46c3a001ff7d5b82cb65fc92f96d9d2b206474bcecc7eeee1981365d2a07fd4dad460edc54a8bc9c8b1e6c7412f7cde3
7
+ data.tar.gz: 35cc1394b526edd0782468b06d54f66eb1ff10e5741becf486f68f0b141511fad9db622816004a4ae2e1a59cff048abe2d5697848eff127640663e9246f33cca
data/bin/stackprof CHANGED
@@ -2,31 +2,33 @@
2
2
  require 'optparse'
3
3
  require 'stackprof'
4
4
 
5
+ banner = <<-END
6
+ Usage: stackprof run [--mode=MODE|--out=FILE|--interval=INTERVAL|--format=FORMAT] -- COMMAND
7
+ Usage: stackprof [file.dump]+ [--text|--method=NAME|--callgrind|--graphviz]
8
+ END
9
+
5
10
  if ARGV.first == "run"
6
11
  ARGV.shift
7
12
  env = {}
8
- parser = OptionParser.new(ARGV) do |o|
9
- o.banner = "Usage: stackprof run [--mode|--out|--interval] -- COMMAND"
10
- o.banner = "Usage: stackprof [file.dump]+ [--text|--method=NAME|--callgrind|--graphviz]"
11
-
12
- o.on('--mode', 'Mode of sampling: cpu, wall, object, default to wall') do |mode|
13
+ parser = OptionParser.new(banner) do |o|
14
+ o.on('--mode [MODE]', String, 'Mode of sampling: cpu, wall, object, default to wall') do |mode|
13
15
  env["STACKPROF_MODE"] = mode
14
16
  end
15
17
 
16
- o.on('--out', 'The target file, which will be overwritten. Defaults to a random temporary file') do |out|
18
+ o.on('--out [FILENAME]', String, 'The target file, which will be overwritten. Defaults to a random temporary file') do |out|
17
19
  env['STACKPROF_OUT'] = out
18
20
  end
19
21
 
20
- o.on('--interval', 'Mode-relative sample rate') do |interval|
21
- env['STACKPROF_INTERVAL'] = Integer(interval).to_s
22
+ o.on('--interval [MILLISECONDS]', Integer, 'Mode-relative sample rate') do |interval|
23
+ env['STACKPROF_INTERVAL'] = interval.to_s
22
24
  end
23
25
 
24
- o.on('--raw', 'collects the extra data required by the --flamegraph and --stackcollapse report types') do
25
- env['STACKPROF_RAW'] = '1'
26
+ o.on('--raw', 'collects the extra data required by the --flamegraph and --stackcollapse report types') do |raw|
27
+ env['STACKPROF_RAW'] = raw.to_s
26
28
  end
27
29
 
28
- o.on('--ignore-gc', 'Ignore garbage collection frames') do
29
- env['STACKPROF_IGNORE_GC'] = '1'
30
+ o.on('--ignore-gc', 'Ignore garbage collection frames') do |gc|
31
+ env['STACKPROF_IGNORE_GC'] = gc.to_s
30
32
  end
31
33
  end
32
34
  parser.parse!
@@ -37,10 +39,7 @@ if ARGV.first == "run"
37
39
  else
38
40
  options = {}
39
41
 
40
- parser = OptionParser.new(ARGV) do |o|
41
- o.banner = "Usage: stackprof run [--mode|--out|--interval] -- COMMAND"
42
- o.banner = "Usage: stackprof [file.dump]+ [--text|--method=NAME|--callgrind|--graphviz]"
43
-
42
+ parser = OptionParser.new(banner) do |o|
44
43
  o.on('--text', 'Text summary per method (default)'){ options[:format] = :text }
45
44
  o.on('--json', 'JSON output (use with web viewers)'){ options[:format] = :json }
46
45
  o.on('--files', 'List of files'){ |f| options[:format] = :files }
@@ -12,6 +12,7 @@
12
12
  #include <ruby/st.h>
13
13
  #include <ruby/io.h>
14
14
  #include <ruby/intern.h>
15
+ #include <ruby/vm.h>
15
16
  #include <signal.h>
16
17
  #include <sys/time.h>
17
18
  #include <time.h>
@@ -32,6 +33,7 @@ static const char *fake_frame_cstrs[] = {
32
33
  };
33
34
 
34
35
  static int stackprof_use_postponed_job = 1;
36
+ static int ruby_vm_running = 0;
35
37
 
36
38
  #define TOTAL_FAKE_FRAMES (sizeof(fake_frame_cstrs) / sizeof(char *))
37
39
 
@@ -125,6 +127,8 @@ static struct {
125
127
  sample_time_t buffer_time;
126
128
  VALUE frames_buffer[BUF_SIZE];
127
129
  int lines_buffer[BUF_SIZE];
130
+
131
+ pthread_t target_thread;
128
132
  } _stackprof;
129
133
 
130
134
  static VALUE sym_object, sym_wall, sym_cpu, sym_custom, sym_name, sym_file, sym_line;
@@ -219,6 +223,7 @@ stackprof_start(int argc, VALUE *argv, VALUE self)
219
223
  _stackprof.ignore_gc = ignore_gc;
220
224
  _stackprof.metadata = metadata;
221
225
  _stackprof.out = out;
226
+ _stackprof.target_thread = pthread_self();
222
227
 
223
228
  if (raw) {
224
229
  capture_timestamp(&_stackprof.last_sample_at);
@@ -721,7 +726,27 @@ stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext)
721
726
  _stackprof.overall_signals++;
722
727
 
723
728
  if (!_stackprof.running) return;
724
- if (!ruby_native_thread_p()) return;
729
+
730
+ // There's a possibility that the signal handler is invoked *after* the Ruby
731
+ // VM has been shut down (e.g. after ruby_cleanup(0)). In this case, things
732
+ // that rely on global VM state (e.g. rb_during_gc) will segfault.
733
+ if (!ruby_vm_running) return;
734
+
735
+ if (_stackprof.mode == sym_wall) {
736
+ // In "wall" mode, the SIGALRM signal will arrive at an arbitrary thread.
737
+ // In order to provide more useful results, especially under threaded web
738
+ // servers, we want to forward this signal to the original thread
739
+ // StackProf was started from.
740
+ // According to POSIX.1-2008 TC1 pthread_kill and pthread_self should be
741
+ // async-signal-safe.
742
+ if (pthread_self() != _stackprof.target_thread) {
743
+ pthread_kill(_stackprof.target_thread, sig);
744
+ return;
745
+ }
746
+ } else {
747
+ if (!ruby_native_thread_p()) return;
748
+ }
749
+
725
750
  if (pthread_mutex_trylock(&lock)) return;
726
751
 
727
752
  if (!_stackprof.ignore_gc && rb_during_gc()) {
@@ -827,6 +852,12 @@ stackprof_use_postponed_job_l(VALUE self)
827
852
  return Qnil;
828
853
  }
829
854
 
855
+ static void
856
+ stackprof_at_exit(ruby_vm_t* vm)
857
+ {
858
+ ruby_vm_running = 0;
859
+ }
860
+
830
861
  void
831
862
  Init_stackprof(void)
832
863
  {
@@ -837,6 +868,9 @@ Init_stackprof(void)
837
868
  */
838
869
  stackprof_use_postponed_job = RUBY_API_VERSION_MAJOR < 3;
839
870
 
871
+ ruby_vm_running = 1;
872
+ ruby_vm_at_exit(stackprof_at_exit);
873
+
840
874
  #define S(name) sym_##name = ID2SYM(rb_intern(#name));
841
875
  S(object);
842
876
  S(custom);
data/lib/stackprof.rb CHANGED
@@ -6,10 +6,15 @@ end
6
6
 
7
7
  if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
8
8
  StackProf.use_postponed_job!
9
+ elsif RUBY_VERSION == "3.2.0"
10
+ # 3.2.0 crash is the signal is received at the wrong time.
11
+ # Fixed in https://github.com/ruby/ruby/pull/7116
12
+ # The fix is backported in 3.2.1: https://bugs.ruby-lang.org/issues/19336
13
+ StackProf.use_postponed_job!
9
14
  end
10
15
 
11
16
  module StackProf
12
- VERSION = '0.2.22'
17
+ VERSION = '0.2.24'
13
18
  end
14
19
 
15
20
  StackProf.autoload :Report, "stackprof/report.rb"
data/stackprof.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'stackprof'
3
- s.version = '0.2.22'
3
+ s.version = '0.2.24'
4
4
  s.homepage = 'http://github.com/tmm1/stackprof'
5
5
 
6
6
  s.authors = 'Aman Gupta'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stackprof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.22
4
+ version: 0.2.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aman Gupta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-13 00:00:00.000000000 Z
11
+ date: 2023-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -99,9 +99,9 @@ licenses:
99
99
  - MIT
100
100
  metadata:
101
101
  bug_tracker_uri: https://github.com/tmm1/stackprof/issues
102
- changelog_uri: https://github.com/tmm1/stackprof/blob/v0.2.22/CHANGELOG.md
103
- documentation_uri: https://www.rubydoc.info/gems/stackprof/0.2.22
104
- source_code_uri: https://github.com/tmm1/stackprof/tree/v0.2.22
102
+ changelog_uri: https://github.com/tmm1/stackprof/blob/v0.2.24/CHANGELOG.md
103
+ documentation_uri: https://www.rubydoc.info/gems/stackprof/0.2.24
104
+ source_code_uri: https://github.com/tmm1/stackprof/tree/v0.2.24
105
105
  post_install_message:
106
106
  rdoc_options: []
107
107
  require_paths: