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