add feature to enable/disable markers
[lttng-ust.git] / libust / 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>
3a7b90de 9#include <poll.h>
fbd8191b
PMF
10
11#include "marker.h"
a584bc4e 12#include "tracer.h"
d0b5f2b9
PMF
13#include "localerr.h"
14#include "ustcomm.h"
46ef48cd 15#include "relay.h" /* FIXME: remove */
fbd8191b 16
b02e31e5 17//#define USE_CLONE
3847c3ba 18
68c1021b
PMF
19#define USTSIGNAL SIGIO
20
98963de4
PMF
21#define MAX_MSG_SIZE (100)
22#define MSG_NOTIF 1
23#define MSG_REGISTER_NOTIF 2
24
a584bc4e
PMF
25char consumer_stack[10000];
26
3a7b90de
PMF
27struct list_head blocked_consumers = LIST_HEAD_INIT(blocked_consumers);
28
d0b5f2b9
PMF
29static struct ustcomm_app ustcomm_app;
30
68c1021b
PMF
31struct tracecmd { /* no padding */
32 uint32_t size;
33 uint16_t command;
34};
35
98963de4
PMF
36//struct listener_arg {
37// int pipe_fd;
38//};
39
40struct trctl_msg {
41 /* size: the size of all the fields except size itself */
42 uint32_t size;
43 uint16_t type;
44 /* Only the necessary part of the payload is transferred. It
45 * may even be none of it.
46 */
47 char payload[94];
48};
68c1021b 49
a584bc4e
PMF
50struct consumer_channel {
51 int fd;
52 struct ltt_channel_struct *chan;
53};
54
3a7b90de
PMF
55struct blocked_consumer {
56 int fd_consumer;
57 int fd_producer;
58 int tmp_poll_idx;
59
60 /* args to ustcomm_send_reply */
61 struct ustcomm_server server;
62 struct ustcomm_source src;
63
64 /* args to ltt_do_get_subbuf */
65 struct rchan_buf *rbuf;
66 struct ltt_channel_buf_struct *lttbuf;
67
68 struct list_head list;
69};
70
52c51a47 71static void print_markers(FILE *fp)
fbd8191b
PMF
72{
73 struct marker_iter iter;
74
d0b5f2b9 75 lock_markers();
fbd8191b
PMF
76 marker_iter_reset(&iter);
77 marker_iter_start(&iter);
78
79 while(iter.marker) {
52c51a47 80 fprintf(fp, "marker: %s_%s %d \"%s\"\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format);
fbd8191b
PMF
81 marker_iter_next(&iter);
82 }
d0b5f2b9 83 unlock_markers();
fbd8191b
PMF
84}
85
68c1021b
PMF
86void do_command(struct tracecmd *cmd)
87{
88}
89
90void receive_commands()
91{
92}
93
98963de4
PMF
94int fd_notif = -1;
95void notif_cb(void)
96{
97 int result;
98 struct trctl_msg msg;
99
100 /* FIXME: fd_notif should probably be protected by a spinlock */
101
102 if(fd_notif == -1)
103 return;
104
105 msg.type = MSG_NOTIF;
106 msg.size = sizeof(msg.type);
107
108 /* FIXME: don't block here */
109 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
110 if(result == -1) {
111 PERROR("write");
112 return;
113 }
114}
115
d0b5f2b9
PMF
116static int inform_consumer_daemon(void)
117{
3847c3ba
PMF
118 ustcomm_request_consumer(getpid(), "metadata");
119 ustcomm_request_consumer(getpid(), "ust");
d0b5f2b9 120}
fbd8191b 121
3a7b90de
PMF
122void process_blocked_consumers(void)
123{
124 int n_fds = 0;
125 struct pollfd *fds;
126 struct blocked_consumer *bc;
127 int idx = 0;
128 char inbuf;
129 int result;
130
131 list_for_each_entry(bc, &blocked_consumers, list) {
132 n_fds++;
133 }
134
135 fds = (struct pollfd *) malloc(n_fds * sizeof(struct pollfd));
136 if(fds == NULL) {
137 ERR("malloc returned NULL");
138 return;
139 }
140
141 list_for_each_entry(bc, &blocked_consumers, list) {
142 fds[idx].fd = bc->fd_producer;
143 fds[idx].events = POLLIN;
144 bc->tmp_poll_idx = idx;
145 idx++;
146 }
147
148 result = poll(fds, n_fds, 0);
149 if(result == -1) {
150 PERROR("poll");
151 return -1;
152 }
153
154 list_for_each_entry(bc, &blocked_consumers, list) {
155 if(fds[bc->tmp_poll_idx].revents) {
156 long consumed_old = 0;
157 char *reply;
158
159 result = read(bc->fd_producer, &inbuf, 1);
160 if(result == -1) {
161 PERROR("read");
162 continue;
163 }
164 if(result == 0) {
165 DBG("PRODUCER END");
166
167 close(bc->fd_producer);
168
169 __list_del(bc->list.prev, bc->list.next);
170
171 result = ustcomm_send_reply(&bc->server, "END", &bc->src);
172 if(result < 0) {
173 ERR("ustcomm_send_reply failed");
174 continue;
175 }
176
177 continue;
178 }
179
180 result = ltt_do_get_subbuf(bc->rbuf, bc->lttbuf, &consumed_old);
181 if(result == -EAGAIN) {
182 WARN("missed buffer?");
183 continue;
184 }
185 else if(result < 0) {
186 DBG("ltt_do_get_subbuf: error: %s", strerror(-result));
187 }
188 asprintf(&reply, "%s %ld", "OK", consumed_old);
189 result = ustcomm_send_reply(&bc->server, reply, &bc->src);
190 if(result < 0) {
191 ERR("ustcomm_send_reply failed");
192 free(reply);
193 continue;
194 }
195 free(reply);
196
197 __list_del(bc->list.prev, bc->list.next);
198 }
199 }
200
201}
202
98963de4
PMF
203int listener_main(void *p)
204{
205 int result;
206
b0540e11
PMF
207 DBG("LISTENER");
208
98963de4 209 for(;;) {
98963de4 210 uint32_t size;
98963de4
PMF
211 struct sockaddr_un addr;
212 socklen_t addrlen = sizeof(addr);
aafb1650
PMF
213 char trace_name[] = "auto";
214 char trace_type[] = "ustrelay";
d0b5f2b9
PMF
215 char *recvbuf;
216 int len;
b02e31e5 217 struct ustcomm_source src;
98963de4 218
3a7b90de
PMF
219 process_blocked_consumers();
220
221 result = ustcomm_app_recv_message(&ustcomm_app, &recvbuf, &src, 5);
222 if(result < 0) {
d0b5f2b9
PMF
223 WARN("error in ustcomm_app_recv_message");
224 continue;
225 }
3a7b90de
PMF
226 else if(result == 0) {
227 /* no message */
228 continue;
229 }
98963de4 230
d0b5f2b9
PMF
231 DBG("received a message! it's: %s\n", recvbuf);
232 len = strlen(recvbuf);
98963de4 233
d0b5f2b9 234 if(!strcmp(recvbuf, "print_markers")) {
52c51a47
PMF
235 print_markers(stderr);
236 }
237 else if(!strcmp(recvbuf, "list_markers")) {
238 char *ptr;
239 size_t size;
240 FILE *fp;
241
242 fp = open_memstream(&ptr, &size);
243 print_markers(fp);
244 fclose(fp);
245
246 result = ustcomm_send_reply(&ustcomm_app.server, ptr, &src);
247
248 free(ptr);
249 }
250 else if(!strcmp(recvbuf, "start")) {
251 /* start is an operation that setups the trace, allocates it and starts it */
252 result = ltt_trace_setup(trace_name);
253 if(result < 0) {
254 ERR("ltt_trace_setup failed");
255 return;
256 }
257
258 result = ltt_trace_set_type(trace_name, trace_type);
259 if(result < 0) {
260 ERR("ltt_trace_set_type failed");
261 return;
262 }
263
264 result = ltt_trace_alloc(trace_name);
265 if(result < 0) {
266 ERR("ltt_trace_alloc failed");
267 return;
268 }
269
270 inform_consumer_daemon();
271
272 result = ltt_trace_start(trace_name);
273 if(result < 0) {
274 ERR("ltt_trace_start failed");
275 continue;
276 }
d0b5f2b9
PMF
277 }
278 else if(!strcmp(recvbuf, "trace_setup")) {
279 DBG("trace setup");
fbd8191b 280
d0b5f2b9
PMF
281 result = ltt_trace_setup(trace_name);
282 if(result < 0) {
283 ERR("ltt_trace_setup failed");
284 return;
fbd8191b 285 }
d0b5f2b9
PMF
286
287 result = ltt_trace_set_type(trace_name, trace_type);
288 if(result < 0) {
289 ERR("ltt_trace_set_type failed");
290 return;
fbd8191b 291 }
d0b5f2b9
PMF
292 }
293 else if(!strcmp(recvbuf, "trace_alloc")) {
294 DBG("trace alloc");
295
296 result = ltt_trace_alloc(trace_name);
297 if(result < 0) {
298 ERR("ltt_trace_alloc failed");
299 return;
fbd8191b 300 }
d0b5f2b9
PMF
301 }
302 else if(!strcmp(recvbuf, "trace_start")) {
303 DBG("trace start");
304
305 result = ltt_trace_start(trace_name);
306 if(result < 0) {
307 ERR("ltt_trace_start failed");
308 continue;
fbd8191b 309 }
d0b5f2b9
PMF
310 }
311 else if(!strcmp(recvbuf, "trace_stop")) {
312 DBG("trace stop");
313
314 result = ltt_trace_stop(trace_name);
315 if(result < 0) {
316 ERR("ltt_trace_stop failed");
317 return;
aafb1650 318 }
d0b5f2b9
PMF
319 }
320 else if(!strcmp(recvbuf, "trace_destroy")) {
aafb1650 321
d0b5f2b9 322 DBG("trace destroy");
aafb1650 323
d0b5f2b9
PMF
324 result = ltt_trace_destroy(trace_name);
325 if(result < 0) {
326 ERR("ltt_trace_destroy failed");
327 return;
fbd8191b 328 }
98963de4 329 }
b02e31e5 330 else if(nth_token_is(recvbuf, "get_shmid", 0) == 1) {
3847c3ba
PMF
331 struct ltt_trace_struct *trace;
332 char trace_name[] = "auto";
333 int i;
811e4b93 334 char *channel_name;
3847c3ba
PMF
335
336 DBG("get_shmid");
337
811e4b93
PMF
338 channel_name = nth_token(recvbuf, 1);
339 if(channel_name == NULL) {
340 ERR("get_shmid: cannot parse channel");
341 goto next_cmd;
342 }
343
3847c3ba
PMF
344 ltt_lock_traces();
345 trace = _ltt_trace_find(trace_name);
346 ltt_unlock_traces();
347
348 if(trace == NULL) {
349 CPRINTF("cannot find trace!");
350 return 1;
351 }
352
353 for(i=0; i<trace->nr_channels; i++) {
354 struct rchan *rchan = trace->channels[i].trans_channel_data;
355 struct rchan_buf *rbuf = rchan->buf;
8cefc145
PMF
356 struct ltt_channel_struct *ltt_channel = (struct ltt_channel_struct *)rchan->private_data;
357 struct ltt_channel_buf_struct *ltt_buf = ltt_channel->buf;
3847c3ba 358
811e4b93
PMF
359 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
360 char *reply;
361
362 DBG("the shmid for the requested channel is %d", rbuf->shmid);
8cefc145
PMF
363 DBG("the shmid for its buffer structure is %d", ltt_channel->buf_shmid);
364 asprintf(&reply, "%d %d", rbuf->shmid, ltt_channel->buf_shmid);
811e4b93
PMF
365
366 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
367 if(result) {
368 ERR("listener: get_shmid: ustcomm_send_reply failed");
369 goto next_cmd;
370 }
371
372 free(reply);
373
374 break;
375 }
376 }
377 }
378 else if(nth_token_is(recvbuf, "get_n_subbufs", 0) == 1) {
379 struct ltt_trace_struct *trace;
380 char trace_name[] = "auto";
381 int i;
382 char *channel_name;
383
384 DBG("get_n_subbufs");
385
386 channel_name = nth_token(recvbuf, 1);
387 if(channel_name == NULL) {
388 ERR("get_n_subbufs: cannot parse channel");
389 goto next_cmd;
390 }
391
392 ltt_lock_traces();
393 trace = _ltt_trace_find(trace_name);
394 ltt_unlock_traces();
395
396 if(trace == NULL) {
397 CPRINTF("cannot find trace!");
398 return 1;
399 }
400
401 for(i=0; i<trace->nr_channels; i++) {
402 struct rchan *rchan = trace->channels[i].trans_channel_data;
403
404 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
405 char *reply;
406
407 DBG("the n_subbufs for the requested channel is %d", rchan->n_subbufs);
408 asprintf(&reply, "%d", rchan->n_subbufs);
409
410 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
411 if(result) {
412 ERR("listener: get_n_subbufs: ustcomm_send_reply failed");
413 goto next_cmd;
414 }
415
416 free(reply);
417
418 break;
419 }
420 }
421 }
422 else if(nth_token_is(recvbuf, "get_subbuf_size", 0) == 1) {
423 struct ltt_trace_struct *trace;
424 char trace_name[] = "auto";
425 int i;
426 char *channel_name;
427
428 DBG("get_subbuf_size");
429
430 channel_name = nth_token(recvbuf, 1);
431 if(channel_name == NULL) {
432 ERR("get_subbuf_size: cannot parse channel");
433 goto next_cmd;
434 }
435
436 ltt_lock_traces();
437 trace = _ltt_trace_find(trace_name);
438 ltt_unlock_traces();
439
440 if(trace == NULL) {
441 CPRINTF("cannot find trace!");
442 return 1;
443 }
444
445 for(i=0; i<trace->nr_channels; i++) {
446 struct rchan *rchan = trace->channels[i].trans_channel_data;
447
448 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
449 char *reply;
450
451 DBG("the subbuf_size for the requested channel is %d", rchan->subbuf_size);
452 asprintf(&reply, "%d", rchan->subbuf_size);
453
454 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
455 if(result) {
456 ERR("listener: get_subbuf_size: ustcomm_send_reply failed");
457 goto next_cmd;
458 }
459
460 free(reply);
3847c3ba 461
811e4b93
PMF
462 break;
463 }
3847c3ba
PMF
464 }
465 }
b02e31e5
PMF
466 else if(nth_token_is(recvbuf, "load_probe_lib", 0) == 1) {
467 char *libfile;
468
469 libfile = nth_token(recvbuf, 1);
470
471 DBG("load_probe_lib loading %s", libfile);
472 }
688760ef
PMF
473 else if(nth_token_is(recvbuf, "get_subbuffer", 0) == 1) {
474 struct ltt_trace_struct *trace;
475 char trace_name[] = "auto";
476 int i;
477 char *channel_name;
478
479 DBG("get_subbuf");
480
481 channel_name = nth_token(recvbuf, 1);
482 if(channel_name == NULL) {
483 ERR("get_subbuf: cannot parse channel");
484 goto next_cmd;
485 }
486
487 ltt_lock_traces();
488 trace = _ltt_trace_find(trace_name);
489 ltt_unlock_traces();
490
491 if(trace == NULL) {
492 CPRINTF("cannot find trace!");
493 return 1;
494 }
495
496 for(i=0; i<trace->nr_channels; i++) {
497 struct rchan *rchan = trace->channels[i].trans_channel_data;
498
499 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
500 struct rchan_buf *rbuf = rchan->buf;
501 struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
502 char *reply;
503 long consumed_old=0;
3a7b90de
PMF
504 int fd;
505 struct blocked_consumer *bc;
688760ef 506
3a7b90de
PMF
507 bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer));
508 if(bc == NULL) {
509 ERR("malloc returned NULL");
688760ef
PMF
510 goto next_cmd;
511 }
3a7b90de
PMF
512 bc->fd_consumer = src.fd;
513 bc->fd_producer = lttbuf->data_ready_fd_read;
514 bc->rbuf = rbuf;
515 bc->lttbuf = lttbuf;
516 bc->src = src;
517 bc->server = ustcomm_app.server;
688760ef 518
3a7b90de 519 list_add(&bc->list, &blocked_consumers);
688760ef
PMF
520
521 break;
522 }
523 }
524 }
525 else if(nth_token_is(recvbuf, "put_subbuffer", 0) == 1) {
526 struct ltt_trace_struct *trace;
527 char trace_name[] = "auto";
528 int i;
529 char *channel_name;
530 long consumed_old;
531 char *consumed_old_str;
532 char *endptr;
533
534 DBG("put_subbuf");
535
536 channel_name = strdup_malloc(nth_token(recvbuf, 1));
537 if(channel_name == NULL) {
538 ERR("put_subbuf_size: cannot parse channel");
539 goto next_cmd;
540 }
541
542 consumed_old_str = strdup_malloc(nth_token(recvbuf, 2));
543 if(consumed_old_str == NULL) {
544 ERR("put_subbuf: cannot parse consumed_old");
545 goto next_cmd;
546 }
547 consumed_old = strtol(consumed_old_str, &endptr, 10);
548 if(*endptr != '\0') {
549 ERR("put_subbuf: invalid value for consumed_old");
550 goto next_cmd;
551 }
552
553 ltt_lock_traces();
554 trace = _ltt_trace_find(trace_name);
555 ltt_unlock_traces();
556
557 if(trace == NULL) {
558 CPRINTF("cannot find trace!");
559 return 1;
560 }
561
562 for(i=0; i<trace->nr_channels; i++) {
563 struct rchan *rchan = trace->channels[i].trans_channel_data;
564
565 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
566 struct rchan_buf *rbuf = rchan->buf;
567 struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
568 char *reply;
569 long consumed_old=0;
570
571 result = ltt_do_put_subbuf(rbuf, lttbuf, consumed_old);
572 if(result < 0) {
573 WARN("ltt_do_put_subbuf: error");
574 }
575 else {
576 DBG("ltt_do_put_subbuf: success");
577 }
578 asprintf(&reply, "%s", "OK", consumed_old);
579
580 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
581 if(result) {
582 ERR("listener: put_subbuf: ustcomm_send_reply failed");
583 goto next_cmd;
584 }
585
586 free(reply);
587
588 break;
589 }
590 }
591
592 free(channel_name);
593 free(consumed_old_str);
594 }
52c51a47
PMF
595 else if(nth_token_is(recvbuf, "enable_marker", 0) == 1) {
596 char *channel_slash_name = nth_token(recvbuf, 1);
597 char channel_name[256]="";
598 char marker_name[256]="";
599 struct marker_iter iter;
600
601 result = sscanf(channel_slash_name, "%255[^/]/%255s", channel_name, marker_name);
602
603 if(channel_name == NULL || marker_name == NULL) {
604 WARN("invalid marker name");
605 goto next_cmd;
606 }
607 printf("%s %s\n", channel_name, marker_name);
608
609 result = ltt_marker_connect(channel_name, marker_name, "default");
610 if(result < 0) {
611 WARN("could not enable marker; channel=%s, name=%s", channel_name, marker_name);
612 }
613 }
614 else if(nth_token_is(recvbuf, "disable_marker", 0) == 1) {
615 char *channel_slash_name = nth_token(recvbuf, 1);
616 char *marker_name;
617 char *channel_name;
618 struct marker_iter iter;
619
620 result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
621
622 if(marker_name == NULL) {
623 }
624 printf("%s %s\n", channel_name, marker_name);
625
626 result = ltt_marker_disconnect(channel_name, marker_name, "default");
627 if(result < 0) {
628 WARN("could not disable marker; channel=%s, name=%s", channel_name, marker_name);
629 }
630 }
3a7b90de
PMF
631// else if(nth_token_is(recvbuf, "get_notifications", 0) == 1) {
632// struct ltt_trace_struct *trace;
633// char trace_name[] = "auto";
634// int i;
635// char *channel_name;
636//
637// DBG("get_notifications");
638//
639// channel_name = strdup_malloc(nth_token(recvbuf, 1));
640// if(channel_name == NULL) {
641// ERR("put_subbuf_size: cannot parse channel");
642// goto next_cmd;
643// }
644//
645// ltt_lock_traces();
646// trace = _ltt_trace_find(trace_name);
647// ltt_unlock_traces();
648//
649// if(trace == NULL) {
650// CPRINTF("cannot find trace!");
651// return 1;
652// }
653//
654// for(i=0; i<trace->nr_channels; i++) {
655// struct rchan *rchan = trace->channels[i].trans_channel_data;
656// int fd;
657//
658// if(!strcmp(trace->channels[i].channel_name, channel_name)) {
659// struct rchan_buf *rbuf = rchan->buf;
660// struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
661//
662// result = fd = ustcomm_app_detach_client(&ustcomm_app, &src);
663// if(result == -1) {
664// ERR("ustcomm_app_detach_client failed");
665// goto next_cmd;
666// }
667//
668// lttbuf->wake_consumer_arg = (void *) fd;
669//
670// smp_wmb();
671//
672// lttbuf->call_wake_consumer = 1;
673//
674// break;
675// }
676// }
677//
678// free(channel_name);
679// }
688760ef
PMF
680 else {
681 ERR("unable to parse message: %s", recvbuf);
682 }
d0b5f2b9 683
811e4b93 684 next_cmd:
d0b5f2b9 685 free(recvbuf);
98963de4
PMF
686 }
687}
688
b0540e11
PMF
689static char listener_stack[16384];
690
98963de4
PMF
691void create_listener(void)
692{
693 int result;
694 static char listener_stack[16384];
b0540e11 695 //char *listener_stack = malloc(16384);
98963de4 696
3847c3ba 697#ifdef USE_CLONE
fbd8191b 698 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
98963de4
PMF
699 if(result == -1) {
700 perror("clone");
701 }
3847c3ba
PMF
702#else
703 pthread_t thread;
b0540e11 704
3847c3ba
PMF
705 pthread_create(&thread, NULL, listener_main, NULL);
706#endif
98963de4
PMF
707}
708
d0b5f2b9
PMF
709/* The signal handler itself. Signals must be setup so there cannot be
710 nested signals. */
68c1021b
PMF
711
712void sighandler(int sig)
713{
d0b5f2b9 714 static char have_listener = 0;
68c1021b 715 DBG("sighandler");
d0b5f2b9
PMF
716
717 if(!have_listener) {
718 create_listener();
719 have_listener = 1;
720 }
68c1021b
PMF
721}
722
723/* Called by the app signal handler to chain it to us. */
724
98963de4 725void chain_signal(void)
68c1021b
PMF
726{
727 sighandler(USTSIGNAL);
728}
729
98963de4 730static int init_socket(void)
68c1021b 731{
d0b5f2b9 732 return ustcomm_init_app(getpid(), &ustcomm_app);
68c1021b
PMF
733}
734
98963de4 735static void destroy_socket(void)
68c1021b 736{
46ef48cd
PMF
737// int result;
738//
739// if(mysocketfile[0] == '\0')
740// return;
741//
742// result = unlink(mysocketfile);
743// if(result == -1) {
744// PERROR("unlink");
745// }
68c1021b
PMF
746}
747
98963de4 748static int init_signal_handler(void)
68c1021b
PMF
749{
750 /* Attempt to handler SIGIO. If the main program wants to
751 * handle it, fine, it'll override us. They it'll have to
752 * use the chaining function.
753 */
754
755 int result;
756 struct sigaction act;
757
758 result = sigemptyset(&act.sa_mask);
759 if(result == -1) {
760 PERROR("sigemptyset");
761 return -1;
762 }
763
764 act.sa_handler = sighandler;
765 act.sa_flags = SA_RESTART;
766
767 /* Only defer ourselves. Also, try to restart interrupted
768 * syscalls to disturb the traced program as little as possible.
769 */
770 result = sigaction(SIGIO, &act, NULL);
771 if(result == -1) {
772 PERROR("sigaction");
773 return -1;
774 }
775
776 return 0;
777}
778
20b37a31 779static void auto_probe_connect(struct marker *m)
68c1021b
PMF
780{
781 int result;
782
20b37a31
PMF
783 result = ltt_marker_connect(m->channel, m->name, "default");
784 if(result)
785 ERR("ltt_marker_connect");
786
787 DBG("just auto connected marker %s %s to probe default", m->channel, m->name);
788}
789
790static void __attribute__((constructor(101))) init0()
791{
792 DBG("UST_AUTOPROBE constructor");
793 if(getenv("UST_AUTOPROBE")) {
794 marker_set_new_marker_cb(auto_probe_connect);
795 }
796}
797
a584bc4e
PMF
798static void fini(void);
799
20b37a31
PMF
800static void __attribute__((constructor(1000))) init()
801{
802 int result;
803
804 DBG("UST_TRACE constructor");
805
3847c3ba
PMF
806 /* Must create socket before signal handler to prevent races.
807 */
808 result = init_socket();
809 if(result == -1) {
810 ERR("init_socket error");
811 return;
812 }
813 result = init_signal_handler();
814 if(result == -1) {
815 ERR("init_signal_handler error");
816 return;
817 }
68c1021b 818
4db647c5
PMF
819 if(getenv("UST_TRACE")) {
820 char trace_name[] = "auto";
821 char trace_type[] = "ustrelay";
822
823 DBG("starting early tracing");
824
825 /* Ensure marker control is initialized */
826 init_marker_control();
827
828 /* Ensure relay is initialized */
829 init_ustrelay_transport();
830
831 /* Ensure markers are initialized */
832 init_markers();
833
20b37a31
PMF
834 /* In case. */
835 ltt_channels_register("ust");
4db647c5
PMF
836
837 result = ltt_trace_setup(trace_name);
838 if(result < 0) {
839 ERR("ltt_trace_setup failed");
840 return;
841 }
842
843 result = ltt_trace_set_type(trace_name, trace_type);
844 if(result < 0) {
845 ERR("ltt_trace_set_type failed");
846 return;
847 }
848
849 result = ltt_trace_alloc(trace_name);
850 if(result < 0) {
851 ERR("ltt_trace_alloc failed");
852 return;
853 }
854
855 result = ltt_trace_start(trace_name);
856 if(result < 0) {
857 ERR("ltt_trace_start failed");
858 return;
859 }
3847c3ba 860 inform_consumer_daemon();
4db647c5
PMF
861 }
862
68c1021b
PMF
863
864 return;
865
866 /* should decrementally destroy stuff if error */
867
868}
869
870/* This is only called if we terminate normally, not with an unhandled signal,
871 * so we cannot rely on it. */
872
98963de4 873static void __attribute__((destructor)) fini()
68c1021b 874{
a584bc4e
PMF
875 int result;
876
877 /* if trace running, finish it */
878
879 DBG("destructor stopping traces");
880
881 result = ltt_trace_stop("auto");
882 if(result == -1) {
883 ERR("ltt_trace_stop error");
884 }
885
886 result = ltt_trace_destroy("auto");
887 if(result == -1) {
888 ERR("ltt_trace_destroy error");
889 }
890
891 /* FIXME: wait for the consumer to be done */
f20de35f
PMF
892 //DBG("waiting 5 sec for consume");
893 //sleep(5);
a584bc4e 894
68c1021b
PMF
895 destroy_socket();
896}
This page took 0.089884 seconds and 4 git commands to generate.