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