make inform_consumer_daemon() generic
[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 #include <regex.h>
29
30 #include <urcu.h>
31
32 #include "marker.h"
33 #include "tracer.h"
34 #include "localerr.h"
35 #include "ustcomm.h"
36 #include "relay.h" /* FIXME: remove */
37 #include "marker-control.h"
38
39 //#define USE_CLONE
40
41 #define USTSIGNAL SIGIO
42
43 #define MAX_MSG_SIZE (100)
44 #define MSG_NOTIF 1
45 #define MSG_REGISTER_NOTIF 2
46
47 char consumer_stack[10000];
48
49 struct list_head blocked_consumers = LIST_HEAD_INIT(blocked_consumers);
50
51 static struct ustcomm_app ustcomm_app;
52
53 struct tracecmd { /* no padding */
54 uint32_t size;
55 uint16_t command;
56 };
57
58 //struct listener_arg {
59 // int pipe_fd;
60 //};
61
62 struct trctl_msg {
63 /* size: the size of all the fields except size itself */
64 uint32_t size;
65 uint16_t type;
66 /* Only the necessary part of the payload is transferred. It
67 * may even be none of it.
68 */
69 char payload[94];
70 };
71
72 struct consumer_channel {
73 int fd;
74 struct ltt_channel_struct *chan;
75 };
76
77 struct blocked_consumer {
78 int fd_consumer;
79 int fd_producer;
80 int tmp_poll_idx;
81
82 /* args to ustcomm_send_reply */
83 struct ustcomm_server server;
84 struct ustcomm_source src;
85
86 /* args to ltt_do_get_subbuf */
87 struct rchan_buf *rbuf;
88 struct ltt_channel_buf_struct *lttbuf;
89
90 struct list_head list;
91 };
92
93 static void print_markers(FILE *fp)
94 {
95 struct marker_iter iter;
96
97 lock_markers();
98 marker_iter_reset(&iter);
99 marker_iter_start(&iter);
100
101 while(iter.marker) {
102 fprintf(fp, "marker: %s_%s %d \"%s\"\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format);
103 marker_iter_next(&iter);
104 }
105 unlock_markers();
106 }
107
108 static int init_socket(void);
109
110 /* This needs to be called whenever a new thread is created. It notifies
111 * liburcu of the new thread.
112 */
113
114 void ust_register_thread(void)
115 {
116 rcu_register_thread();
117 }
118
119 int fd_notif = -1;
120 void notif_cb(void)
121 {
122 int result;
123 struct trctl_msg msg;
124
125 /* FIXME: fd_notif should probably be protected by a spinlock */
126
127 if(fd_notif == -1)
128 return;
129
130 msg.type = MSG_NOTIF;
131 msg.size = sizeof(msg.type);
132
133 /* FIXME: don't block here */
134 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
135 if(result == -1) {
136 PERROR("write");
137 return;
138 }
139 }
140
141 /* Ask the daemon to collect a trace called trace_name and being
142 * produced by this pid.
143 *
144 * The trace must be at least allocated. (It can also be started.)
145 * This is because _ltt_trace_find is used.
146 */
147
148 static void inform_consumer_daemon(const char *trace_name)
149 {
150 int i;
151 struct ltt_trace_struct *trace;
152 pid_t pid = getpid();
153 int result;
154
155 ltt_lock_traces();
156
157 trace = _ltt_trace_find(trace_name);
158 if(trace == NULL) {
159 WARN("inform_consumer_daemon: could not find trace \"%s\"; it is probably already destroyed", trace_name);
160 goto finish;
161 }
162
163 for(i=0; i < trace->nr_channels; i++) {
164 result = ustcomm_request_consumer(pid, trace->channels[i].channel_name);
165 if(result == -1) {
166 WARN("Failed to request collection for channel %s. Is the daemon available?", trace->channels[i].channel_name);
167 /* continue even if fail */
168 }
169 }
170
171 finish:
172 ltt_unlock_traces();
173 }
174
175 void process_blocked_consumers(void)
176 {
177 int n_fds = 0;
178 struct pollfd *fds;
179 struct blocked_consumer *bc;
180 int idx = 0;
181 char inbuf;
182 int result;
183
184 list_for_each_entry(bc, &blocked_consumers, list) {
185 n_fds++;
186 }
187
188 fds = (struct pollfd *) malloc(n_fds * sizeof(struct pollfd));
189 if(fds == NULL) {
190 ERR("malloc returned NULL");
191 return;
192 }
193
194 list_for_each_entry(bc, &blocked_consumers, list) {
195 fds[idx].fd = bc->fd_producer;
196 fds[idx].events = POLLIN;
197 bc->tmp_poll_idx = idx;
198 idx++;
199 }
200
201 while((result = poll(fds, n_fds, 0)) == -1 && errno == EINTR)
202 /* nothing */;
203 if(result == -1) {
204 PERROR("poll");
205 return;
206 }
207
208 list_for_each_entry(bc, &blocked_consumers, list) {
209 if(fds[bc->tmp_poll_idx].revents) {
210 long consumed_old = 0;
211 char *reply;
212
213 result = read(bc->fd_producer, &inbuf, 1);
214 if(result == -1) {
215 PERROR("read");
216 continue;
217 }
218 if(result == 0) {
219 DBG("PRODUCER END");
220
221 close(bc->fd_producer);
222
223 list_del(&bc->list);
224
225 result = ustcomm_send_reply(&bc->server, "END", &bc->src);
226 if(result < 0) {
227 ERR("ustcomm_send_reply failed");
228 continue;
229 }
230
231 continue;
232 }
233
234 result = ltt_do_get_subbuf(bc->rbuf, bc->lttbuf, &consumed_old);
235 if(result == -EAGAIN) {
236 WARN("missed buffer?");
237 continue;
238 }
239 else if(result < 0) {
240 DBG("ltt_do_get_subbuf: error: %s", strerror(-result));
241 }
242 asprintf(&reply, "%s %ld", "OK", consumed_old);
243 result = ustcomm_send_reply(&bc->server, reply, &bc->src);
244 if(result < 0) {
245 ERR("ustcomm_send_reply failed");
246 free(reply);
247 continue;
248 }
249 free(reply);
250
251 list_del(&bc->list);
252 }
253 }
254
255 }
256
257 void *listener_main(void *p)
258 {
259 int result;
260
261 ust_register_thread();
262
263 DBG("LISTENER");
264
265 for(;;) {
266 char trace_name[] = "auto";
267 char trace_type[] = "ustrelay";
268 char *recvbuf;
269 int len;
270 struct ustcomm_source src;
271
272 process_blocked_consumers();
273
274 result = ustcomm_app_recv_message(&ustcomm_app, &recvbuf, &src, 5);
275 if(result < 0) {
276 WARN("error in ustcomm_app_recv_message");
277 continue;
278 }
279 else if(result == 0) {
280 /* no message */
281 continue;
282 }
283
284 DBG("received a message! it's: %s", recvbuf);
285 len = strlen(recvbuf);
286
287 if(!strcmp(recvbuf, "print_markers")) {
288 print_markers(stderr);
289 }
290 else if(!strcmp(recvbuf, "list_markers")) {
291 char *ptr;
292 size_t size;
293 FILE *fp;
294
295 fp = open_memstream(&ptr, &size);
296 print_markers(fp);
297 fclose(fp);
298
299 result = ustcomm_send_reply(&ustcomm_app.server, ptr, &src);
300
301 free(ptr);
302 }
303 else if(!strcmp(recvbuf, "start")) {
304 /* start is an operation that setups the trace, allocates it and starts it */
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 result = ltt_trace_alloc(trace_name);
318 if(result < 0) {
319 ERR("ltt_trace_alloc failed");
320 return (void *)1;
321 }
322
323 inform_consumer_daemon(trace_name);
324
325 result = ltt_trace_start(trace_name);
326 if(result < 0) {
327 ERR("ltt_trace_start failed");
328 continue;
329 }
330 }
331 else if(!strcmp(recvbuf, "trace_setup")) {
332 DBG("trace setup");
333
334 result = ltt_trace_setup(trace_name);
335 if(result < 0) {
336 ERR("ltt_trace_setup failed");
337 return (void *)1;
338 }
339
340 result = ltt_trace_set_type(trace_name, trace_type);
341 if(result < 0) {
342 ERR("ltt_trace_set_type failed");
343 return (void *)1;
344 }
345 }
346 else if(!strcmp(recvbuf, "trace_alloc")) {
347 DBG("trace alloc");
348
349 result = ltt_trace_alloc(trace_name);
350 if(result < 0) {
351 ERR("ltt_trace_alloc failed");
352 return (void *)1;
353 }
354 }
355 else if(!strcmp(recvbuf, "trace_start")) {
356 DBG("trace start");
357
358 result = ltt_trace_start(trace_name);
359 if(result < 0) {
360 ERR("ltt_trace_start failed");
361 continue;
362 }
363 }
364 else if(!strcmp(recvbuf, "trace_stop")) {
365 DBG("trace stop");
366
367 result = ltt_trace_stop(trace_name);
368 if(result < 0) {
369 ERR("ltt_trace_stop failed");
370 return (void *)1;
371 }
372 }
373 else if(!strcmp(recvbuf, "trace_destroy")) {
374
375 DBG("trace destroy");
376
377 result = ltt_trace_destroy(trace_name);
378 if(result < 0) {
379 ERR("ltt_trace_destroy failed");
380 return (void *)1;
381 }
382 }
383 else if(nth_token_is(recvbuf, "get_shmid", 0) == 1) {
384 struct ltt_trace_struct *trace;
385 char trace_name[] = "auto";
386 int i;
387 char *channel_name;
388
389 DBG("get_shmid");
390
391 channel_name = nth_token(recvbuf, 1);
392 if(channel_name == NULL) {
393 ERR("get_shmid: cannot parse channel");
394 goto next_cmd;
395 }
396
397 ltt_lock_traces();
398 trace = _ltt_trace_find(trace_name);
399 ltt_unlock_traces();
400
401 if(trace == NULL) {
402 ERR("cannot find trace!");
403 return (void *)1;
404 }
405
406 for(i=0; i<trace->nr_channels; i++) {
407 struct rchan *rchan = trace->channels[i].trans_channel_data;
408 struct rchan_buf *rbuf = rchan->buf;
409 struct ltt_channel_struct *ltt_channel = (struct ltt_channel_struct *)rchan->private_data;
410
411 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
412 char *reply;
413
414 DBG("the shmid for the requested channel is %d", rbuf->shmid);
415 DBG("the shmid for its buffer structure is %d", ltt_channel->buf_shmid);
416 asprintf(&reply, "%d %d", rbuf->shmid, ltt_channel->buf_shmid);
417
418 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
419 if(result) {
420 ERR("listener: get_shmid: ustcomm_send_reply failed");
421 goto next_cmd;
422 }
423
424 free(reply);
425
426 break;
427 }
428 }
429 }
430 else if(nth_token_is(recvbuf, "get_n_subbufs", 0) == 1) {
431 struct ltt_trace_struct *trace;
432 char trace_name[] = "auto";
433 int i;
434 char *channel_name;
435
436 DBG("get_n_subbufs");
437
438 channel_name = nth_token(recvbuf, 1);
439 if(channel_name == NULL) {
440 ERR("get_n_subbufs: cannot parse channel");
441 goto next_cmd;
442 }
443
444 ltt_lock_traces();
445 trace = _ltt_trace_find(trace_name);
446 ltt_unlock_traces();
447
448 if(trace == NULL) {
449 ERR("cannot find trace!");
450 return (void *)1;
451 }
452
453 for(i=0; i<trace->nr_channels; i++) {
454 struct rchan *rchan = trace->channels[i].trans_channel_data;
455
456 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
457 char *reply;
458
459 DBG("the n_subbufs for the requested channel is %zd", rchan->n_subbufs);
460 asprintf(&reply, "%zd", rchan->n_subbufs);
461
462 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
463 if(result) {
464 ERR("listener: get_n_subbufs: ustcomm_send_reply failed");
465 goto next_cmd;
466 }
467
468 free(reply);
469
470 break;
471 }
472 }
473 }
474 else if(nth_token_is(recvbuf, "get_subbuf_size", 0) == 1) {
475 struct ltt_trace_struct *trace;
476 char trace_name[] = "auto";
477 int i;
478 char *channel_name;
479
480 DBG("get_subbuf_size");
481
482 channel_name = nth_token(recvbuf, 1);
483 if(channel_name == NULL) {
484 ERR("get_subbuf_size: cannot parse channel");
485 goto next_cmd;
486 }
487
488 ltt_lock_traces();
489 trace = _ltt_trace_find(trace_name);
490 ltt_unlock_traces();
491
492 if(trace == NULL) {
493 ERR("cannot find trace!");
494 return (void *)1;
495 }
496
497 for(i=0; i<trace->nr_channels; i++) {
498 struct rchan *rchan = trace->channels[i].trans_channel_data;
499
500 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
501 char *reply;
502
503 DBG("the subbuf_size for the requested channel is %zd", rchan->subbuf_size);
504 asprintf(&reply, "%zd", rchan->subbuf_size);
505
506 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
507 if(result) {
508 ERR("listener: get_subbuf_size: ustcomm_send_reply failed");
509 goto next_cmd;
510 }
511
512 free(reply);
513
514 break;
515 }
516 }
517 }
518 else if(nth_token_is(recvbuf, "load_probe_lib", 0) == 1) {
519 char *libfile;
520
521 libfile = nth_token(recvbuf, 1);
522
523 DBG("load_probe_lib loading %s", libfile);
524 }
525 else if(nth_token_is(recvbuf, "get_subbuffer", 0) == 1) {
526 struct ltt_trace_struct *trace;
527 char trace_name[] = "auto";
528 int i;
529 char *channel_name;
530
531 DBG("get_subbuf");
532
533 channel_name = nth_token(recvbuf, 1);
534 if(channel_name == NULL) {
535 ERR("get_subbuf: cannot parse channel");
536 goto next_cmd;
537 }
538
539 ltt_lock_traces();
540 trace = _ltt_trace_find(trace_name);
541 ltt_unlock_traces();
542
543 if(trace == NULL) {
544 ERR("cannot find trace!");
545 return (void *)1;
546 }
547
548 for(i=0; i<trace->nr_channels; i++) {
549 struct rchan *rchan = trace->channels[i].trans_channel_data;
550
551 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
552 struct rchan_buf *rbuf = rchan->buf;
553 struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
554 struct blocked_consumer *bc;
555
556 bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer));
557 if(bc == NULL) {
558 ERR("malloc returned NULL");
559 goto next_cmd;
560 }
561 bc->fd_consumer = src.fd;
562 bc->fd_producer = lttbuf->data_ready_fd_read;
563 bc->rbuf = rbuf;
564 bc->lttbuf = lttbuf;
565 bc->src = src;
566 bc->server = ustcomm_app.server;
567
568 list_add(&bc->list, &blocked_consumers);
569
570 break;
571 }
572 }
573 }
574 else if(nth_token_is(recvbuf, "put_subbuffer", 0) == 1) {
575 struct ltt_trace_struct *trace;
576 char trace_name[] = "auto";
577 int i;
578 char *channel_name;
579 long consumed_old;
580 char *consumed_old_str;
581 char *endptr;
582
583 DBG("put_subbuf");
584
585 channel_name = strdup_malloc(nth_token(recvbuf, 1));
586 if(channel_name == NULL) {
587 ERR("put_subbuf_size: cannot parse channel");
588 goto next_cmd;
589 }
590
591 consumed_old_str = strdup_malloc(nth_token(recvbuf, 2));
592 if(consumed_old_str == NULL) {
593 ERR("put_subbuf: cannot parse consumed_old");
594 goto next_cmd;
595 }
596 consumed_old = strtol(consumed_old_str, &endptr, 10);
597 if(*endptr != '\0') {
598 ERR("put_subbuf: invalid value for consumed_old");
599 goto next_cmd;
600 }
601
602 ltt_lock_traces();
603 trace = _ltt_trace_find(trace_name);
604 ltt_unlock_traces();
605
606 if(trace == NULL) {
607 ERR("cannot find trace!");
608 return (void *)1;
609 }
610
611 for(i=0; i<trace->nr_channels; i++) {
612 struct rchan *rchan = trace->channels[i].trans_channel_data;
613
614 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
615 struct rchan_buf *rbuf = rchan->buf;
616 struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
617 char *reply;
618 long consumed_old=0;
619
620 result = ltt_do_put_subbuf(rbuf, lttbuf, consumed_old);
621 if(result < 0) {
622 WARN("ltt_do_put_subbuf: error (subbuf=%s)", channel_name);
623 asprintf(&reply, "%s", "ERROR");
624 }
625 else {
626 DBG("ltt_do_put_subbuf: success (subbuf=%s)", channel_name);
627 asprintf(&reply, "%s", "OK");
628 }
629
630 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
631 if(result) {
632 ERR("listener: put_subbuf: ustcomm_send_reply failed");
633 goto next_cmd;
634 }
635
636 free(reply);
637
638 break;
639 }
640 }
641
642 free(channel_name);
643 free(consumed_old_str);
644 }
645 else if(nth_token_is(recvbuf, "enable_marker", 0) == 1) {
646 char *channel_slash_name = nth_token(recvbuf, 1);
647 char channel_name[256]="";
648 char marker_name[256]="";
649
650 result = sscanf(channel_slash_name, "%255[^/]/%255s", channel_name, marker_name);
651
652 if(channel_name == NULL || marker_name == NULL) {
653 WARN("invalid marker name");
654 goto next_cmd;
655 }
656 printf("%s %s\n", channel_name, marker_name);
657
658 result = ltt_marker_connect(channel_name, marker_name, "default");
659 if(result < 0) {
660 WARN("could not enable marker; channel=%s, name=%s", channel_name, marker_name);
661 }
662 }
663 else if(nth_token_is(recvbuf, "disable_marker", 0) == 1) {
664 char *channel_slash_name = nth_token(recvbuf, 1);
665 char *marker_name;
666 char *channel_name;
667
668 result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
669
670 if(marker_name == NULL) {
671 }
672 printf("%s %s\n", channel_name, marker_name);
673
674 result = ltt_marker_disconnect(channel_name, marker_name, "default");
675 if(result < 0) {
676 WARN("could not disable marker; channel=%s, name=%s", channel_name, marker_name);
677 }
678 }
679 // else if(nth_token_is(recvbuf, "get_notifications", 0) == 1) {
680 // struct ltt_trace_struct *trace;
681 // char trace_name[] = "auto";
682 // int i;
683 // char *channel_name;
684 //
685 // DBG("get_notifications");
686 //
687 // channel_name = strdup_malloc(nth_token(recvbuf, 1));
688 // if(channel_name == NULL) {
689 // ERR("put_subbuf_size: cannot parse channel");
690 // goto next_cmd;
691 // }
692 //
693 // ltt_lock_traces();
694 // trace = _ltt_trace_find(trace_name);
695 // ltt_unlock_traces();
696 //
697 // if(trace == NULL) {
698 // ERR("cannot find trace!");
699 // return (void *)1;
700 // }
701 //
702 // for(i=0; i<trace->nr_channels; i++) {
703 // struct rchan *rchan = trace->channels[i].trans_channel_data;
704 // int fd;
705 //
706 // if(!strcmp(trace->channels[i].channel_name, channel_name)) {
707 // struct rchan_buf *rbuf = rchan->buf;
708 // struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
709 //
710 // result = fd = ustcomm_app_detach_client(&ustcomm_app, &src);
711 // if(result == -1) {
712 // ERR("ustcomm_app_detach_client failed");
713 // goto next_cmd;
714 // }
715 //
716 // lttbuf->wake_consumer_arg = (void *) fd;
717 //
718 // smp_wmb();
719 //
720 // lttbuf->call_wake_consumer = 1;
721 //
722 // break;
723 // }
724 // }
725 //
726 // free(channel_name);
727 // }
728 else {
729 ERR("unable to parse message: %s", recvbuf);
730 }
731
732 next_cmd:
733 free(recvbuf);
734 }
735 }
736
737 int have_listener = 0;
738
739 void create_listener(void)
740 {
741 #ifdef USE_CLONE
742 static char listener_stack[16384];
743 #else
744 pthread_t thread;
745 #endif
746
747 if(have_listener)
748 return;
749
750 #ifdef USE_CLONE
751 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
752 if(result == -1) {
753 perror("clone");
754 return;
755 }
756 #else
757
758 pthread_create(&thread, NULL, listener_main, NULL);
759 #endif
760
761 have_listener = 1;
762 }
763
764 /* The signal handler itself. Signals must be setup so there cannot be
765 nested signals. */
766
767 void sighandler(int sig)
768 {
769 static char have_listener = 0;
770 DBG("sighandler");
771
772 if(!have_listener) {
773 create_listener();
774 have_listener = 1;
775 }
776 }
777
778 /* Called by the app signal handler to chain it to us. */
779
780 void chain_signal(void)
781 {
782 sighandler(USTSIGNAL);
783 }
784
785 static int init_socket(void)
786 {
787 return ustcomm_init_app(getpid(), &ustcomm_app);
788 }
789
790 /* FIXME: reenable this to delete socket file. */
791
792 #if 0
793 static void destroy_socket(void)
794 {
795 int result;
796
797 if(mysocketfile[0] == '\0')
798 return;
799
800 result = unlink(mysocketfile);
801 if(result == -1) {
802 PERROR("unlink");
803 }
804 }
805 #endif
806
807 static int init_signal_handler(void)
808 {
809 /* Attempt to handler SIGIO. If the main program wants to
810 * handle it, fine, it'll override us. They it'll have to
811 * use the chaining function.
812 */
813
814 int result;
815 struct sigaction act;
816
817 result = sigemptyset(&act.sa_mask);
818 if(result == -1) {
819 PERROR("sigemptyset");
820 return -1;
821 }
822
823 act.sa_handler = sighandler;
824 act.sa_flags = SA_RESTART;
825
826 /* Only defer ourselves. Also, try to restart interrupted
827 * syscalls to disturb the traced program as little as possible.
828 */
829 result = sigaction(SIGIO, &act, NULL);
830 if(result == -1) {
831 PERROR("sigaction");
832 return -1;
833 }
834
835 return 0;
836 }
837
838 #define AUTOPROBE_DISABLED 0
839 #define AUTOPROBE_ENABLE_ALL 1
840 #define AUTOPROBE_ENABLE_REGEX 2
841 static int autoprobe_method = AUTOPROBE_DISABLED;
842 static regex_t autoprobe_regex;
843
844 static void auto_probe_connect(struct marker *m)
845 {
846 int result;
847
848 char* concat_name = NULL;
849 const char *probe_name = "default";
850
851 if(autoprobe_method == AUTOPROBE_DISABLED) {
852 return;
853 }
854 else if(autoprobe_method == AUTOPROBE_ENABLE_REGEX) {
855 result = asprintf(&concat_name, "%s/%s", m->channel, m->name);
856 if(result == -1) {
857 ERR("auto_probe_connect: asprintf failed (marker %s/%s)",
858 m->channel, m->name);
859 return;
860 }
861 if (regexec(&autoprobe_regex, concat_name, 0, NULL, 0)) {
862 free(concat_name);
863 return;
864 }
865 free(concat_name);
866 }
867
868 result = ltt_marker_connect(m->channel, m->name, probe_name);
869 if(result && result != -EEXIST)
870 ERR("ltt_marker_connect (marker = %s/%s, errno = %d)", m->channel, m->name, -result);
871
872 DBG("auto connected marker %s %s to probe default", m->channel, m->name);
873
874 }
875
876 static void __attribute__((constructor(1000))) init()
877 {
878 int result;
879 char* autoprobe_val = NULL;
880
881 /* Initialize RCU in case the constructor order is not good. */
882 urcu_init();
883
884 /* It is important to do this before events start to be generated. */
885 ust_register_thread();
886
887 DBG("Tracectl constructor");
888
889 /* Must create socket before signal handler to prevent races.
890 */
891 result = init_socket();
892 if(result == -1) {
893 ERR("init_socket error");
894 return;
895 }
896 result = init_signal_handler();
897 if(result == -1) {
898 ERR("init_signal_handler error");
899 return;
900 }
901
902 autoprobe_val = getenv("UST_AUTOPROBE");
903 if(autoprobe_val) {
904 struct marker_iter iter;
905
906 DBG("Autoprobe enabled.");
907
908 /* Ensure markers are initialized */
909 //init_markers();
910
911 /* Ensure marker control is initialized, for the probe */
912 init_marker_control();
913
914 /* first, set the callback that will connect the
915 * probe on new markers
916 */
917 if(autoprobe_val[0] == '/') {
918 result = regcomp(&autoprobe_regex, autoprobe_val+1, 0);
919 if (result) {
920 char regexerr[150];
921
922 regerror(result, &autoprobe_regex, regexerr, sizeof(regexerr));
923 ERR("cannot parse regex %s (%s), will ignore UST_AUTOPROBE", autoprobe_val, regexerr);
924 /* don't crash the application just for this */
925 }
926 else {
927 autoprobe_method = AUTOPROBE_ENABLE_REGEX;
928 }
929 }
930 else {
931 /* just enable all instrumentation */
932 autoprobe_method = AUTOPROBE_ENABLE_ALL;
933 }
934
935 marker_set_new_marker_cb(auto_probe_connect);
936
937 /* Now, connect the probes that were already registered. */
938 marker_iter_reset(&iter);
939 marker_iter_start(&iter);
940
941 DBG("now iterating on markers already registered");
942 while(iter.marker) {
943 DBG("now iterating on marker %s", iter.marker->name);
944 auto_probe_connect(iter.marker);
945 marker_iter_next(&iter);
946 }
947 }
948
949 if(getenv("UST_TRACE")) {
950 char trace_name[] = "auto";
951 char trace_type[] = "ustrelay";
952
953 DBG("starting early tracing");
954
955 /* Ensure marker control is initialized */
956 init_marker_control();
957
958 /* Ensure relay is initialized */
959 init_ustrelay_transport();
960
961 /* Ensure markers are initialized */
962 init_markers();
963
964 /* In case. */
965 ltt_channels_register("ust");
966
967 result = ltt_trace_setup(trace_name);
968 if(result < 0) {
969 ERR("ltt_trace_setup failed");
970 return;
971 }
972
973 result = ltt_trace_set_type(trace_name, trace_type);
974 if(result < 0) {
975 ERR("ltt_trace_set_type failed");
976 return;
977 }
978
979 result = ltt_trace_alloc(trace_name);
980 if(result < 0) {
981 ERR("ltt_trace_alloc failed");
982 return;
983 }
984
985 inform_consumer_daemon(trace_name);
986
987 result = ltt_trace_start(trace_name);
988 if(result < 0) {
989 ERR("ltt_trace_start failed");
990 return;
991 }
992 }
993
994
995 return;
996
997 /* should decrementally destroy stuff if error */
998
999 }
1000
1001 /* This is only called if we terminate normally, not with an unhandled signal,
1002 * so we cannot rely on it. */
1003
1004 /* This destructor probably isn't needed, because ustd can do crash recovery. */
1005 #if 0
1006 static void __attribute__((destructor)) fini()
1007 {
1008 int result;
1009
1010 /* if trace running, finish it */
1011
1012 DBG("destructor stopping traces");
1013
1014 result = ltt_trace_stop("auto");
1015 if(result == -1) {
1016 ERR("ltt_trace_stop error");
1017 }
1018
1019 result = ltt_trace_destroy("auto");
1020 if(result == -1) {
1021 ERR("ltt_trace_destroy error");
1022 }
1023
1024 destroy_socket();
1025 }
1026 #endif
1027
1028 #if 0
1029 static int trace_recording(void)
1030 {
1031 int retval = 0;
1032 struct ltt_trace_struct *trace;
1033
1034 ltt_lock_traces();
1035
1036 list_for_each_entry(trace, &ltt_traces.head, list) {
1037 if(trace->active) {
1038 retval = 1;
1039 break;
1040 }
1041 }
1042
1043 ltt_unlock_traces();
1044
1045 return retval;
1046 }
1047
1048 static int have_consumer(void)
1049 {
1050 return !list_empty(&blocked_consumers);
1051 }
1052
1053 /* This destructor keeps the process alive for a few seconds in order
1054 * to leave time to ustd to consume its buffers.
1055 */
1056
1057 int restarting_sleep(int secs)
1058 {
1059 struct timespec tv;
1060 int result;
1061
1062 tv.tv_sec = secs;
1063 tv.tv_nsec = 0;
1064
1065 do {
1066 result = nanosleep(&tv, &tv);
1067 } while(result == -1 && errno == EINTR);
1068
1069 return result;
1070 }
1071
1072 static void __attribute__((destructor)) keepalive()
1073 {
1074 // struct ustcomm_ustd ustd;
1075 // int result;
1076 // sigset_t sigset;
1077 //
1078 // result = sigemptyset(&sigset);
1079 // if(result == -1) {
1080 // perror("sigemptyset");
1081 // return;
1082 // }
1083 // result = sigaddset(&sigset, SIGIO);
1084 // if(result == -1) {
1085 // perror("sigaddset");
1086 // return;
1087 // }
1088 // result = sigprocmask(SIG_BLOCK, &sigset, NULL);
1089 // if(result == -1) {
1090 // perror("sigprocmask");
1091 // return;
1092 // }
1093 //
1094 // if(trace_recording()) {
1095 // if(!have_consumer()) {
1096 // /* Request listener creation. We've blocked SIGIO's in
1097 // * order to not interrupt sleep(), so we will miss the
1098 // * one sent by the daemon and therefore won't create
1099 // * the listener automatically.
1100 // */
1101 // create_listener();
1102 //
1103 printf("Keeping process alive for consumer daemon...\n");
1104 restarting_sleep(3);
1105 printf("Finally dying...\n");
1106 // }
1107 // }
1108 //
1109 // result = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1110 // if(result == -1) {
1111 // perror("sigprocmask");
1112 // return;
1113 // }
1114 }
1115 #endif
1116
1117 /* Notify ust that there was a fork. This needs to be called inside
1118 * the new process, anytime a process whose memory is not shared with
1119 * the parent is created. If this function is not called, the events
1120 * of the new process will not be collected.
1121 */
1122
1123 void ust_fork(void)
1124 {
1125 DBG("ust: forking");
1126 ltt_trace_stop("auto");
1127 ltt_trace_destroy("auto");
1128 ltt_trace_alloc("auto");
1129 ltt_trace_start("auto");
1130 init_socket();
1131 have_listener = 0;
1132 create_listener();
1133 inform_consumer_daemon("auto");
1134 }
1135
This page took 0.050571 seconds and 5 git commands to generate.