rbtrace 0.3.20 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/bin/rbtrace +31 -9
- data/ext/rbtrace.c +45 -35
- data/rbtrace.gemspec +1 -1
- data/test.sh +1 -1
- metadata +1 -1
data/Gemfile.lock
CHANGED
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 @
|
172
|
+
break if @qo > -1
|
165
173
|
end
|
166
174
|
|
167
|
-
if @
|
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
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
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.
|
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 =
|
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, "
|
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, "
|
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.
|
801
|
-
|
802
|
-
rbtracer.
|
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.
|
824
|
-
rbtracer.
|
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
data/test.sh
CHANGED