rbtrace 0.3.20 → 0.4.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.
- 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