rbtrace 0.3.20 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/Gemfile.lock +1 -1
  2. data/bin/rbtrace +31 -9
  3. data/ext/rbtrace.c +45 -35
  4. data/rbtrace.gemspec +1 -1
  5. data/test.sh +1 -1
  6. metadata +1 -1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rbtrace (0.3.19)
4
+ rbtrace (0.4.0)
5
5
  ffi (>= 1.0.6)
6
6
  msgpack (>= 0.4.3)
7
7
  trollop (>= 1.16.2)
data/bin/rbtrace CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ require 'socket'
3
+ require 'fileutils'
2
4
  require 'rubygems'
3
5
  require 'ffi'
4
6
  require 'msgpack'
@@ -154,17 +156,23 @@ class RBTracer
154
156
  raise ArgumentError, 'could not signal process, are you running as root?'
155
157
  end
156
158
 
159
+ path = "/tmp/rbtrace-#{@pid}.sock"
160
+ @sock = Socket.new Socket::AF_UNIX, Socket::SOCK_DGRAM, 0
161
+ @sockaddr = Socket.pack_sockaddr_un(path)
162
+ @sock.bind(@sockaddr)
163
+ FileUtils.chmod 0666, path
164
+ at_exit{ FileUtils.rm(path) if File.exists?(path) }
165
+
157
166
  5.times do
158
167
  signal
159
168
  sleep 0.15 # wait for process to create msgqs
160
169
 
161
- @qi = MsgQ.msgget( pid, 0666)
162
170
  @qo = MsgQ.msgget(-pid, 0666)
163
171
 
164
- break if @qi > -1 || @qo > -1
172
+ break if @qo > -1
165
173
  end
166
174
 
167
- if @qi == -1 || @qo == -1
175
+ if @qo == -1
168
176
  raise ArgumentError, 'pid is not listening for messages, did you `require "rbtrace"`'
169
177
  end
170
178
 
@@ -419,11 +427,13 @@ class RBTracer
419
427
  end
420
428
 
421
429
  def recv_cmd(block=true)
422
- MsgQ::EventMsg.recv_cmd(@qi, block)
423
- rescue Errno::EINTR
424
- # on linux, an incoming signal will interrupt msgrcv()
425
- # regardless of what SA_RESTART is set to
426
- retry
430
+ if block
431
+ @sock.recv(65536)
432
+ else
433
+ @sock.recv_nonblock(65536)
434
+ end
435
+ rescue Errno::EAGAIN
436
+ nil
427
437
  end
428
438
 
429
439
  def valid_syntax?(code)
@@ -811,6 +821,10 @@ EOS
811
821
  :type => String,
812
822
  :short => '-e'
813
823
 
824
+ opt :backtrace,
825
+ "get lines from the current backtrace in the process",
826
+ :type => :int
827
+
814
828
  opt :wait,
815
829
  "seconds to wait before attaching to process",
816
830
  :default => 0,
@@ -834,7 +848,7 @@ EOS
834
848
  ARGV.clear
835
849
  end
836
850
 
837
- unless %w[ fork eval slow slowcpu firehose methods config gc ].find{ |n| opts[:"#{n}_given"] }
851
+ unless %w[ fork eval backtrace slow slowcpu firehose methods config gc ].find{ |n| opts[:"#{n}_given"] }
838
852
  $stderr.puts "Error: --slow, --slowcpu, --gc, --firehose, --methods or --config required."
839
853
  $stderr.puts "Try --help for help."
840
854
  exit(-1)
@@ -1011,6 +1025,14 @@ EOS
1011
1025
  pid = tracer.fork
1012
1026
  STDERR.puts "*** forked off a busy looping copy at #{pid} (make sure to kill -9 it when you're done)"
1013
1027
 
1028
+ elsif opts[:backtrace_given]
1029
+ num = opts[:backtrace]
1030
+ code = "caller.first(#{num}).join('|')"
1031
+
1032
+ if res = tracer.eval(code)
1033
+ tracer.puts res[1..-2].split('|').join("\n ")
1034
+ end
1035
+
1014
1036
  elsif opts[:eval_given]
1015
1037
  if res = tracer.eval(code = opts[:eval])
1016
1038
  tracer.puts ">> #{code}"
data/ext/rbtrace.c CHANGED
@@ -12,8 +12,10 @@
12
12
  #include <sys/ipc.h>
13
13
  #include <sys/msg.h>
14
14
  #include <sys/resource.h>
15
+ #include <sys/socket.h>
15
16
  #include <sys/time.h>
16
17
  #include <sys/types.h>
18
+ #include <sys/un.h>
17
19
  #include <sys/wait.h>
18
20
  #include <time.h>
19
21
  #include <unistd.h>
@@ -108,11 +110,13 @@ static struct {
108
110
  unsigned int num_slow;
109
111
  rbtracer_t list[MAX_TRACERS];
110
112
 
111
- key_t mqo_key;
112
113
  key_t mqi_key;
113
- int mqo_id;
114
114
  int mqi_id;
115
115
 
116
+ int mqo_fd;
117
+ struct sockaddr_un mqo_addr;
118
+ socklen_t mqo_len;
119
+
116
120
  msgpack_sbuffer *sbuf;
117
121
  msgpack_packer *msgpacker;
118
122
  }
@@ -137,11 +141,12 @@ rbtracer = {
137
141
  .num_slow = 0,
138
142
  .list = {},
139
143
 
140
- .mqo_key = 0,
141
144
  .mqi_key = 0,
142
- .mqo_id = -1,
143
145
  .mqi_id = -1,
144
146
 
147
+ .mqo_fd = -1,
148
+ .mqo_addr = {.sun_family = AF_UNIX},
149
+
145
150
  .sbuf = NULL,
146
151
  .msgpacker = NULL
147
152
  };
@@ -156,7 +161,7 @@ rbtrace__send_event(int nargs, const char *name, ...)
156
161
  if (!rbtracer.attached_pid ||
157
162
  !rbtracer.sbuf ||
158
163
  !rbtracer.msgpacker ||
159
- rbtracer.mqo_id == -1)
164
+ rbtracer.mqo_fd == -1)
160
165
  return;
161
166
 
162
167
  int n;
@@ -232,31 +237,26 @@ rbtrace__send_event(int nargs, const char *name, ...)
232
237
  va_end(ap);
233
238
  }
234
239
 
235
- event_msg_t msg;
236
- msg.mtype = 1;
237
-
238
- if (rbtracer.sbuf->size > sizeof(msg.buf)) {
239
- fprintf(stderr, "rbtrace__send_event(): message is too large (%zd > %zu)\n", rbtracer.sbuf->size, sizeof(msg.buf));
240
- return;
241
- }
242
-
243
- memcpy(msg.buf, rbtracer.sbuf->data, rbtracer.sbuf->size);
244
-
245
240
  int ret = -1;
246
241
  for (n=0; n<10 && ret==-1; n++)
247
- ret = msgsnd(rbtracer.mqo_id, &msg, sizeof(msg)-sizeof(long), IPC_NOWAIT);
242
+ ret = sendto(
243
+ rbtracer.mqo_fd,
244
+ rbtracer.sbuf->data, rbtracer.sbuf->size,
245
+ #ifdef MSG_NOSIGNAL
246
+ MSG_NOSIGNAL,
247
+ #else
248
+ 0,
249
+ #endif
250
+ &rbtracer.mqo_addr, rbtracer.mqo_len
251
+ );
248
252
 
249
- if (ret == -1 && errno == EINVAL) {
250
- fprintf(stderr, "msgsnd(%d): %s [detaching]\n", rbtracer.mqo_id, strerror(errno));
253
+ if (ret == -1 && (errno == EINVAL || errno == ENOENT || errno == ECONNREFUSED || errno == EPIPE)) {
254
+ fprintf(stderr, "sendto(%d): %s [detaching]\n", rbtracer.mqo_fd, strerror(errno));
251
255
 
252
256
  msgq_teardown();
253
257
  rbtracer_detach();
254
258
  } else if (ret == -1) {
255
- fprintf(stderr, "msgsnd(%d): %s\n", rbtracer.mqo_id, strerror(errno));
256
-
257
- struct msqid_ds stat;
258
- msgctl(rbtracer.mqo_id, IPC_STAT, &stat);
259
- fprintf(stderr, "cbytes: %lu, qbytes: %lu, qnum: %lu\n", stat.msg_cbytes, stat.msg_qbytes, stat.msg_qnum);
259
+ fprintf(stderr, "sendto(%d): %s\n", rbtracer.mqo_fd, strerror(errno));
260
260
  }
261
261
  }
262
262
 
@@ -797,11 +797,11 @@ msgq_teardown()
797
797
  {
798
798
  pid_t pid = getpid();
799
799
 
800
- if (rbtracer.mqo_id != -1 && rbtracer.mqo_key == (key_t)pid) {
801
- msgctl(rbtracer.mqo_id, IPC_RMID, NULL);
802
- rbtracer.mqo_id = -1;
803
- rbtracer.mqo_key = 0;
800
+ if (rbtracer.mqo_fd != -1) {
801
+ close(rbtracer.mqo_fd);
802
+ rbtracer.mqo_fd = -1;
804
803
  }
804
+
805
805
  if (rbtracer.mqi_id != -1 && rbtracer.mqi_key == (key_t)-pid) {
806
806
  msgctl(rbtracer.mqi_id, IPC_RMID, NULL);
807
807
  rbtracer.mqi_id = -1;
@@ -819,26 +819,36 @@ static inline void
819
819
  msgq_setup()
820
820
  {
821
821
  pid_t pid = getpid();
822
+ int val;
822
823
 
823
- if (rbtracer.mqo_key != (key_t)pid ||
824
- rbtracer.mqi_key != (key_t)-pid) {
824
+ if (rbtracer.mqi_key != (key_t)-pid ||
825
+ rbtracer.mqo_fd == -1) {
825
826
  msgq_teardown();
826
827
  } else {
827
828
  return;
828
829
  }
829
830
 
830
- rbtracer.mqo_key = (key_t) pid;
831
- rbtracer.mqo_id = msgget(rbtracer.mqo_key, 0666 | IPC_CREAT);
832
-
833
- if (rbtracer.mqo_id == -1)
834
- fprintf(stderr, "msgget() failed to create msgq\n");
835
-
836
831
 
837
832
  rbtracer.mqi_key = (key_t) -pid;
838
833
  rbtracer.mqi_id = msgget(rbtracer.mqi_key, 0666 | IPC_CREAT);
839
834
 
840
835
  if (rbtracer.mqi_id == -1)
841
836
  fprintf(stderr, "msgget() failed to create msgq\n");
837
+
838
+
839
+ rbtracer.mqo_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
840
+ if (rbtracer.mqo_fd == -1)
841
+ fprintf(stderr, "socket() failed to create dgram\n");
842
+
843
+ snprintf(rbtracer.mqo_addr.sun_path, sizeof(rbtracer.mqo_addr.sun_path), "/tmp/rbtrace-%d.sock", pid);
844
+ rbtracer.mqo_len = SUN_LEN(&rbtracer.mqo_addr);
845
+
846
+ val = 65536;
847
+ setsockopt(rbtracer.mqo_fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(int));
848
+ #ifdef SO_NOSIGPIPE
849
+ val = 1;
850
+ setsockopt(rbtracer.mqo_fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(int));
851
+ #endif
842
852
  }
843
853
 
844
854
  static void
data/rbtrace.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rbtrace'
3
- s.version = '0.3.20'
3
+ s.version = '0.4.0'
4
4
  s.homepage = 'http://github.com/tmm1/rbtrace'
5
5
 
6
6
  s.authors = 'Aman Gupta'
data/test.sh CHANGED
@@ -42,6 +42,6 @@ trace --slow=250 --slow-methods sleep
42
42
  trace --gc -m Dir. --slow=250 --slow-methods sleep
43
43
  trace --gc -m Dir. --slow=250
44
44
  trace -m Process. Dir.pwd "Proc#call"
45
- # trace --firehose
45
+ trace --firehose
46
46
 
47
47
  cleanup
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rbtrace
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.20
5
+ version: 0.4.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Aman Gupta