ust: cleanup: move tracing control to tracectl.c
[ust.git] / libtracectl / tracectl.c
CommitLineData
68c1021b
PMF
1#include <stdio.h>
2#include <stdint.h>
3#include <signal.h>
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <sys/un.h>
98963de4 7#include <sched.h>
a584bc4e 8#include <fcntl.h>
fbd8191b
PMF
9
10#include "marker.h"
a584bc4e
PMF
11#include "tracer.h"
12#include "usterr.h"
fbd8191b 13
68c1021b
PMF
14#define UNIX_PATH_MAX 108
15
16//#define SOCKETDIR "/var/run/ust/socks"
17#define SOCKETDIR "/tmp/socks"
18#define SOCKETDIRLEN sizeof(SOCKETDIR)
19#define USTSIGNAL SIGIO
20
21#define DBG(fmt, args...) fprintf(stderr, fmt "\n", ## args)
22#define WARN(fmt, args...) fprintf(stderr, "usertrace: WARNING: " fmt "\n", ## args)
a584bc4e 23#define ERR(fmt, args...) fprintf(stderr, "usertrace: ERROR: " fmt "\n", ## args); fflush(stderr)
68c1021b
PMF
24#define PERROR(call) perror("usertrace: ERROR: " call)
25
98963de4
PMF
26#define MAX_MSG_SIZE (100)
27#define MSG_NOTIF 1
28#define MSG_REGISTER_NOTIF 2
29
a584bc4e
PMF
30char consumer_stack[10000];
31
68c1021b
PMF
32struct tracecmd { /* no padding */
33 uint32_t size;
34 uint16_t command;
35};
36
98963de4
PMF
37//struct listener_arg {
38// int pipe_fd;
39//};
40
41struct trctl_msg {
42 /* size: the size of all the fields except size itself */
43 uint32_t size;
44 uint16_t type;
45 /* Only the necessary part of the payload is transferred. It
46 * may even be none of it.
47 */
48 char payload[94];
49};
68c1021b
PMF
50
51pid_t mypid;
52char mysocketfile[UNIX_PATH_MAX] = "";
98963de4 53int pfd = -1;
68c1021b 54
a584bc4e
PMF
55struct consumer_channel {
56 int fd;
57 struct ltt_channel_struct *chan;
58};
59
60int consumer(void *arg)
61{
62 int result;
63 int fd;
64 char str[] = "Hello, this is the consumer.\n";
65 struct ltt_trace_struct *trace;
66 struct consumer_channel *consumer_channels;
67 int i;
68 char trace_name[] = "auto";
69
70 ltt_lock_traces();
71 trace = _ltt_trace_find(trace_name);
72 ltt_unlock_traces();
73
74 if(trace == NULL) {
75 CPRINTF("cannot find trace!");
76 return 1;
77 }
78
79 consumer_channels = (struct consumer_channel *) malloc(trace->nr_channels * sizeof(struct consumer_channel));
80 if(consumer_channels == NULL) {
81 ERR("malloc returned NULL");
82 return 1;
83 }
84
85 CPRINTF("opening trace files");
86 for(i=0; i<trace->nr_channels; i++) {
87 char tmp[100];
88 struct ltt_channel_struct *chan = &trace->channels[i];
89
90 consumer_channels[i].chan = chan;
91
92 snprintf(tmp, sizeof(tmp), "trace/%s", chan->channel_name);
93 result = consumer_channels[i].fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 00644);
94 if(result == -1) {
95 perror("open");
96 return -1;
97 }
98 CPRINTF("\topened trace file %s", tmp);
99
100 }
101 CPRINTF("done opening trace files");
102
103 for(;;) {
104 /*wait*/
105
106 for(i=0; i<trace->nr_channels; i++) {
107 struct rchan *rchan = consumer_channels[i].chan->trans_channel_data;
108 struct rchan_buf *rbuf = rchan->buf;
109 struct ltt_channel_buf_struct *lttbuf = consumer_channels[i].chan->buf;
110 long consumed_old;
111
112 result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old);
113 if(result < 0) {
114 CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result));
115 }
116 else {
117 CPRINTF("success!");
118
119 result = write(consumer_channels[i].fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096);
120 ltt_do_put_subbuf(rbuf, lttbuf, consumed_old);
121 }
122 }
123
124 sleep(1);
125 }
126
127// CPRINTF("consumer: got a trace: %s with %d channels\n", trace_name, trace->nr_channels);
128//
129// struct ltt_channel_struct *chan = &trace->channels[0];
130//
131// CPRINTF("channel 1 (%s) active=%u", chan->channel_name, chan->active & 1);
132
133// struct rchan *rchan = chan->trans_channel_data;
134// struct rchan_buf *rbuf = rchan->buf;
135// struct ltt_channel_buf_struct *lttbuf = chan->buf;
136// long consumed_old;
137//
138// result = fd = open("trace.out", O_WRONLY | O_CREAT | O_TRUNC, 00644);
139// if(result == -1) {
140// perror("open");
141// return -1;
142// }
143
144// for(;;) {
145// write(STDOUT_FILENO, str, sizeof(str));
146//
147// result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old);
148// if(result < 0) {
149// CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result));
150// }
151// else {
152// CPRINTF("success!");
153//
154// result = write(fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096);
155// ltt_do_put_subbuf(rbuf, lttbuf, consumed_old);
156// }
157//
158// //CPRINTF("There seems to be %ld bytes available", SUBBUF_TRUNC(local_read(&lttbuf->offset), rbuf->chan) - consumed_old);
159// CPRINTF("Commit count %ld", local_read(&lttbuf->commit_count[0]));
160//
161//
162// sleep(1);
163// }
164}
165
166void start_consumer(void)
167{
168 int result;
169
170 result = clone(consumer, consumer_stack+sizeof(consumer_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
171 if(result == -1) {
172 perror("clone");
173 }
174}
fbd8191b
PMF
175
176static void print_markers(void)
177{
178 struct marker_iter iter;
179
180 marker_iter_reset(&iter);
181 marker_iter_start(&iter);
182
183 while(iter.marker) {
184 fprintf(stderr, "marker: %s_%s \"%s\"\n", iter.marker->channel, iter.marker->name, iter.marker->format);
185 marker_iter_next(&iter);
186 }
187}
188
68c1021b
PMF
189void do_command(struct tracecmd *cmd)
190{
191}
192
193void receive_commands()
194{
195}
196
98963de4
PMF
197int fd_notif = -1;
198void notif_cb(void)
199{
200 int result;
201 struct trctl_msg msg;
202
203 /* FIXME: fd_notif should probably be protected by a spinlock */
204
205 if(fd_notif == -1)
206 return;
207
208 msg.type = MSG_NOTIF;
209 msg.size = sizeof(msg.type);
210
211 /* FIXME: don't block here */
212 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
213 if(result == -1) {
214 PERROR("write");
215 return;
216 }
217}
218
fbd8191b
PMF
219char recvbuf[10000];
220
98963de4
PMF
221int listener_main(void *p)
222{
223 int result;
224
98963de4 225 for(;;) {
98963de4 226 uint32_t size;
98963de4
PMF
227 struct sockaddr_un addr;
228 socklen_t addrlen = sizeof(addr);
aafb1650
PMF
229 char trace_name[] = "auto";
230 char trace_type[] = "ustrelay";
98963de4 231
98963de4
PMF
232 for(;;) {
233 struct trctl_msg msg;
fbd8191b 234 int len;
98963de4 235
fbd8191b 236 result = len = recvfrom(pfd, recvbuf, sizeof(recvbuf), 0, &addr, &addrlen);
98963de4 237 if(result == -1) {
fbd8191b 238 PERROR("recvfrom");
98963de4
PMF
239 continue;
240 }
241
aafb1650
PMF
242 if(recvbuf[len-1] == '\n')
243 recvbuf[len-1] = '\0';
98963de4 244
fbd8191b 245 fprintf(stderr, "received a message! it's: %s\n", recvbuf);
98963de4 246
fbd8191b
PMF
247
248 if(!strcmp(recvbuf, "print_markers")) {
249 print_markers();
250 }
251 else if(!strcmp(recvbuf, "trace_setup")) {
252 DBG("trace setup");
aafb1650
PMF
253
254 result = ltt_trace_setup(trace_name);
255 if(result < 0) {
256 ERR("ltt_trace_setup failed");
257 return;
258 }
259
260 result = ltt_trace_set_type(trace_name, trace_type);
261 if(result < 0) {
262 ERR("ltt_trace_set_type failed");
263 return;
264 }
fbd8191b
PMF
265 }
266 else if(!strcmp(recvbuf, "trace_alloc")) {
267 DBG("trace alloc");
aafb1650
PMF
268
269 result = ltt_trace_alloc(trace_name);
270 if(result < 0) {
271 ERR("ltt_trace_alloc failed");
272 return;
273 }
fbd8191b
PMF
274 }
275 else if(!strcmp(recvbuf, "trace_start")) {
276 DBG("trace start");
aafb1650
PMF
277
278 result = ltt_trace_start(trace_name);
279 if(result < 0) {
280 ERR("ltt_trace_start failed");
281 return;
282 }
fbd8191b
PMF
283 }
284 else if(!strcmp(recvbuf, "trace_stop")) {
285 DBG("trace stop");
aafb1650
PMF
286
287 result = ltt_trace_stop(trace_name);
288 if(result < 0) {
289 ERR("ltt_trace_stop failed");
290 return;
291 }
292 }
293 else if(!strcmp(recvbuf, "trace_destroy")) {
294
295 DBG("trace destroy");
296
297 result = ltt_trace_destroy(trace_name);
298 if(result < 0) {
299 ERR("ltt_trace_destroy failed");
300 return;
301 }
fbd8191b 302 }
98963de4
PMF
303 }
304 next_conn:;
305 }
306}
307
308void create_listener(void)
309{
310 int result;
311 static char listener_stack[16384];
312
fbd8191b 313 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
98963de4
PMF
314 if(result == -1) {
315 perror("clone");
316 }
317}
318
68c1021b
PMF
319/* The signal handler itself. */
320
321void sighandler(int sig)
322{
323 DBG("sighandler");
fbd8191b 324 create_listener();
68c1021b
PMF
325}
326
327/* Called by the app signal handler to chain it to us. */
328
98963de4 329void chain_signal(void)
68c1021b
PMF
330{
331 sighandler(USTSIGNAL);
332}
333
98963de4 334static int init_socket(void)
68c1021b
PMF
335{
336 int result;
337 int fd;
338 char pidstr[6];
339 int pidlen;
340
341 struct sockaddr_un addr;
342
fbd8191b 343 result = fd = socket(PF_UNIX, SOCK_DGRAM, 0);
68c1021b
PMF
344 if(result == -1) {
345 PERROR("socket");
346 return -1;
347 }
348
349 addr.sun_family = AF_UNIX;
350
351 result = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%d", SOCKETDIR, mypid);
352 if(result >= UNIX_PATH_MAX) {
353 ERR("string overflow allocating socket name");
354 goto close_sock;
355 }
356 //DBG("opening socket at %s", addr.sun_path);
357
358 result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
359 if(result == -1) {
360 PERROR("bind");
361 goto close_sock;
362 }
363
364 strcpy(mysocketfile, addr.sun_path);
365
98963de4
PMF
366 pfd = fd;
367 return 0;
368
68c1021b
PMF
369 close_sock:
370 close(fd);
371
372 return -1;
373}
374
98963de4 375static void destroy_socket(void)
68c1021b
PMF
376{
377 int result;
378
379 if(mysocketfile[0] == '\0')
380 return;
381
382 result = unlink(mysocketfile);
383 if(result == -1) {
384 PERROR("unlink");
385 }
386}
387
98963de4 388static int init_signal_handler(void)
68c1021b
PMF
389{
390 /* Attempt to handler SIGIO. If the main program wants to
391 * handle it, fine, it'll override us. They it'll have to
392 * use the chaining function.
393 */
394
395 int result;
396 struct sigaction act;
397
398 result = sigemptyset(&act.sa_mask);
399 if(result == -1) {
400 PERROR("sigemptyset");
401 return -1;
402 }
403
404 act.sa_handler = sighandler;
405 act.sa_flags = SA_RESTART;
406
407 /* Only defer ourselves. Also, try to restart interrupted
408 * syscalls to disturb the traced program as little as possible.
409 */
410 result = sigaction(SIGIO, &act, NULL);
411 if(result == -1) {
412 PERROR("sigaction");
413 return -1;
414 }
415
416 return 0;
417}
418
20b37a31 419static void auto_probe_connect(struct marker *m)
68c1021b
PMF
420{
421 int result;
422
20b37a31
PMF
423 result = ltt_marker_connect(m->channel, m->name, "default");
424 if(result)
425 ERR("ltt_marker_connect");
426
427 DBG("just auto connected marker %s %s to probe default", m->channel, m->name);
428}
429
430static void __attribute__((constructor(101))) init0()
431{
432 DBG("UST_AUTOPROBE constructor");
433 if(getenv("UST_AUTOPROBE")) {
434 marker_set_new_marker_cb(auto_probe_connect);
435 }
436}
437
a584bc4e
PMF
438static void fini(void);
439
20b37a31
PMF
440static void __attribute__((constructor(1000))) init()
441{
442 int result;
443
444 DBG("UST_TRACE constructor");
445
68c1021b
PMF
446 mypid = getpid();
447
4db647c5
PMF
448 if(getenv("UST_TRACE")) {
449 char trace_name[] = "auto";
450 char trace_type[] = "ustrelay";
451
452 DBG("starting early tracing");
453
454 /* Ensure marker control is initialized */
455 init_marker_control();
456
457 /* Ensure relay is initialized */
458 init_ustrelay_transport();
459
460 /* Ensure markers are initialized */
461 init_markers();
462
20b37a31
PMF
463 /* In case. */
464 ltt_channels_register("ust");
4db647c5
PMF
465
466 result = ltt_trace_setup(trace_name);
467 if(result < 0) {
468 ERR("ltt_trace_setup failed");
469 return;
470 }
471
472 result = ltt_trace_set_type(trace_name, trace_type);
473 if(result < 0) {
474 ERR("ltt_trace_set_type failed");
475 return;
476 }
477
478 result = ltt_trace_alloc(trace_name);
479 if(result < 0) {
480 ERR("ltt_trace_alloc failed");
481 return;
482 }
483
484 result = ltt_trace_start(trace_name);
485 if(result < 0) {
486 ERR("ltt_trace_start failed");
487 return;
488 }
a584bc4e 489 start_consumer();
4db647c5
PMF
490 }
491
98963de4
PMF
492 /* Must create socket before signal handler to prevent races
493 * on pfd variable.
494 */
68c1021b 495 result = init_socket();
98963de4
PMF
496 if(result == -1) {
497 ERR("init_socket error");
498 return;
499 }
500 result = init_signal_handler();
501 if(result == -1) {
502 ERR("init_signal_handler error");
503 return;
504 }
68c1021b
PMF
505
506 return;
507
508 /* should decrementally destroy stuff if error */
509
510}
511
512/* This is only called if we terminate normally, not with an unhandled signal,
513 * so we cannot rely on it. */
514
98963de4 515static void __attribute__((destructor)) fini()
68c1021b 516{
a584bc4e
PMF
517 int result;
518
519 /* if trace running, finish it */
520
521 DBG("destructor stopping traces");
522
523 result = ltt_trace_stop("auto");
524 if(result == -1) {
525 ERR("ltt_trace_stop error");
526 }
527
528 result = ltt_trace_destroy("auto");
529 if(result == -1) {
530 ERR("ltt_trace_destroy error");
531 }
532
533 /* FIXME: wait for the consumer to be done */
534 sleep(10);
535
68c1021b
PMF
536 destroy_socket();
537}
This page took 0.043226 seconds and 4 git commands to generate.