add feature to enable/disable markers
[ust.git] / libust / tracectl.c
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>
7 #include <sched.h>
8 #include <fcntl.h>
9 #include <poll.h>
10
11 #include "marker.h"
12 #include "tracer.h"
13 #include "localerr.h"
14 #include "ustcomm.h"
15 #include "relay.h" /* FIXME: remove */
16
17 //#define USE_CLONE
18
19 #define USTSIGNAL SIGIO
20
21 #define MAX_MSG_SIZE (100)
22 #define MSG_NOTIF 1
23 #define MSG_REGISTER_NOTIF 2
24
25 char consumer_stack[10000];
26
27 struct list_head blocked_consumers = LIST_HEAD_INIT(blocked_consumers);
28
29 static struct ustcomm_app ustcomm_app;
30
31 struct tracecmd { /* no padding */
32 uint32_t size;
33 uint16_t command;
34 };
35
36 //struct listener_arg {
37 // int pipe_fd;
38 //};
39
40 struct 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 };
49
50 struct consumer_channel {
51 int fd;
52 struct ltt_channel_struct *chan;
53 };
54
55 struct 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
71 static void print_markers(FILE *fp)
72 {
73 struct marker_iter iter;
74
75 lock_markers();
76 marker_iter_reset(&iter);
77 marker_iter_start(&iter);
78
79 while(iter.marker) {
80 fprintf(fp, "marker: %s_%s %d \"%s\"\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format);
81 marker_iter_next(&iter);
82 }
83 unlock_markers();
84 }
85
86 void do_command(struct tracecmd *cmd)
87 {
88 }
89
90 void receive_commands()
91 {
92 }
93
94 int fd_notif = -1;
95 void 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
116 static int inform_consumer_daemon(void)
117 {
118 ustcomm_request_consumer(getpid(), "metadata");
119 ustcomm_request_consumer(getpid(), "ust");
120 }
121
122 void 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
203 int listener_main(void *p)
204 {
205 int result;
206
207 DBG("LISTENER");
208
209 for(;;) {
210 uint32_t size;
211 struct sockaddr_un addr;
212 socklen_t addrlen = sizeof(addr);
213 char trace_name[] = "auto";
214 char trace_type[] = "ustrelay";
215 char *recvbuf;
216 int len;
217 struct ustcomm_source src;
218
219 process_blocked_consumers();
220
221 result = ustcomm_app_recv_message(&ustcomm_app, &recvbuf, &src, 5);
222 if(result < 0) {
223 WARN("error in ustcomm_app_recv_message");
224 continue;
225 }
226 else if(result == 0) {
227 /* no message */
228 continue;
229 }
230
231 DBG("received a message! it's: %s\n", recvbuf);
232 len = strlen(recvbuf);
233
234 if(!strcmp(recvbuf, "print_markers")) {
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 }
277 }
278 else if(!strcmp(recvbuf, "trace_setup")) {
279 DBG("trace setup");
280
281 result = ltt_trace_setup(trace_name);
282 if(result < 0) {
283 ERR("ltt_trace_setup failed");
284 return;
285 }
286
287 result = ltt_trace_set_type(trace_name, trace_type);
288 if(result < 0) {
289 ERR("ltt_trace_set_type failed");
290 return;
291 }
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;
300 }
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;
309 }
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;
318 }
319 }
320 else if(!strcmp(recvbuf, "trace_destroy")) {
321
322 DBG("trace destroy");
323
324 result = ltt_trace_destroy(trace_name);
325 if(result < 0) {
326 ERR("ltt_trace_destroy failed");
327 return;
328 }
329 }
330 else if(nth_token_is(recvbuf, "get_shmid", 0) == 1) {
331 struct ltt_trace_struct *trace;
332 char trace_name[] = "auto";
333 int i;
334 char *channel_name;
335
336 DBG("get_shmid");
337
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
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;
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;
358
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);
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);
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);
461
462 break;
463 }
464 }
465 }
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 }
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;
504 int fd;
505 struct blocked_consumer *bc;
506
507 bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer));
508 if(bc == NULL) {
509 ERR("malloc returned NULL");
510 goto next_cmd;
511 }
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;
518
519 list_add(&bc->list, &blocked_consumers);
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 }
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 }
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 // }
680 else {
681 ERR("unable to parse message: %s", recvbuf);
682 }
683
684 next_cmd:
685 free(recvbuf);
686 }
687 }
688
689 static char listener_stack[16384];
690
691 void create_listener(void)
692 {
693 int result;
694 static char listener_stack[16384];
695 //char *listener_stack = malloc(16384);
696
697 #ifdef USE_CLONE
698 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
699 if(result == -1) {
700 perror("clone");
701 }
702 #else
703 pthread_t thread;
704
705 pthread_create(&thread, NULL, listener_main, NULL);
706 #endif
707 }
708
709 /* The signal handler itself. Signals must be setup so there cannot be
710 nested signals. */
711
712 void sighandler(int sig)
713 {
714 static char have_listener = 0;
715 DBG("sighandler");
716
717 if(!have_listener) {
718 create_listener();
719 have_listener = 1;
720 }
721 }
722
723 /* Called by the app signal handler to chain it to us. */
724
725 void chain_signal(void)
726 {
727 sighandler(USTSIGNAL);
728 }
729
730 static int init_socket(void)
731 {
732 return ustcomm_init_app(getpid(), &ustcomm_app);
733 }
734
735 static void destroy_socket(void)
736 {
737 // int result;
738 //
739 // if(mysocketfile[0] == '\0')
740 // return;
741 //
742 // result = unlink(mysocketfile);
743 // if(result == -1) {
744 // PERROR("unlink");
745 // }
746 }
747
748 static int init_signal_handler(void)
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
779 static void auto_probe_connect(struct marker *m)
780 {
781 int result;
782
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
790 static 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
798 static void fini(void);
799
800 static void __attribute__((constructor(1000))) init()
801 {
802 int result;
803
804 DBG("UST_TRACE constructor");
805
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 }
818
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
834 /* In case. */
835 ltt_channels_register("ust");
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 }
860 inform_consumer_daemon();
861 }
862
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
873 static void __attribute__((destructor)) fini()
874 {
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 */
892 //DBG("waiting 5 sec for consume");
893 //sleep(5);
894
895 destroy_socket();
896 }
This page took 0.046829 seconds and 4 git commands to generate.