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