fix destruction to free all memory
[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 <stdlib.h>
21 #include <stdint.h>
22 #include <signal.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sched.h>
27 #include <fcntl.h>
28 #include <poll.h>
29 #include <regex.h>
30 #include <urcu/uatomic_arch.h>
31
32 #include <ust/marker.h>
33 #include <ust/tracectl.h>
34 #include "tracer.h"
35 #include "usterr.h"
36 #include "ustcomm.h"
37 #include "buffers.h"
38 #include "marker-control.h"
39
40 //#define USE_CLONE
41
42 #define USTSIGNAL SIGIO
43
44 #define MAX_MSG_SIZE (100)
45 #define MSG_NOTIF 1
46 #define MSG_REGISTER_NOTIF 2
47
48 char consumer_stack[10000];
49
50 /* This should only be accessed by the constructor, before the creation
51 * of the listener, and then only by the listener.
52 */
53 s64 pidunique = -1LL;
54
55 struct list_head blocked_consumers = LIST_HEAD_INIT(blocked_consumers);
56
57 static struct ustcomm_app ustcomm_app;
58
59 struct tracecmd { /* no padding */
60 uint32_t size;
61 uint16_t command;
62 };
63
64 /* volatile because shared between the listener and the main thread */
65 volatile sig_atomic_t buffers_to_export = 0;
66
67 struct trctl_msg {
68 /* size: the size of all the fields except size itself */
69 uint32_t size;
70 uint16_t type;
71 /* Only the necessary part of the payload is transferred. It
72 * may even be none of it.
73 */
74 char payload[94];
75 };
76
77 struct consumer_channel {
78 int fd;
79 struct ltt_channel_struct *chan;
80 };
81
82 struct blocked_consumer {
83 int fd_consumer;
84 int fd_producer;
85 int tmp_poll_idx;
86
87 /* args to ustcomm_send_reply */
88 struct ustcomm_server server;
89 struct ustcomm_source src;
90
91 /* args to ust_buffers_get_subbuf */
92 struct ust_buffer *buf;
93
94 struct list_head list;
95 };
96
97 static long long make_pidunique(void)
98 {
99 s64 retval;
100 struct timeval tv;
101
102 gettimeofday(&tv, NULL);
103
104 retval = tv.tv_sec;
105 retval <<= 32;
106 retval |= tv.tv_usec;
107
108 return retval;
109 }
110
111 static void print_markers(FILE *fp)
112 {
113 struct marker_iter iter;
114
115 lock_markers();
116 marker_iter_reset(&iter);
117 marker_iter_start(&iter);
118
119 while(iter.marker) {
120 fprintf(fp, "marker: %s/%s %d \"%s\" %p\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format, iter.marker->location);
121 marker_iter_next(&iter);
122 }
123 unlock_markers();
124 }
125
126 static int init_socket(void);
127
128 int fd_notif = -1;
129 void notif_cb(void)
130 {
131 int result;
132 struct trctl_msg msg;
133
134 /* FIXME: fd_notif should probably be protected by a spinlock */
135
136 if(fd_notif == -1)
137 return;
138
139 msg.type = MSG_NOTIF;
140 msg.size = sizeof(msg.type);
141
142 /* FIXME: don't block here */
143 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
144 if(result == -1) {
145 PERROR("write");
146 return;
147 }
148 }
149
150 /* Ask the daemon to collect a trace called trace_name and being
151 * produced by this pid.
152 *
153 * The trace must be at least allocated. (It can also be started.)
154 * This is because _ltt_trace_find is used.
155 */
156
157 static void inform_consumer_daemon(const char *trace_name)
158 {
159 int i,j;
160 struct ust_trace *trace;
161 pid_t pid = getpid();
162 int result;
163
164 ltt_lock_traces();
165
166 trace = _ltt_trace_find(trace_name);
167 if(trace == NULL) {
168 WARN("inform_consumer_daemon: could not find trace \"%s\"; it is probably already destroyed", trace_name);
169 goto finish;
170 }
171
172 for(i=0; i < trace->nr_channels; i++) {
173 /* iterate on all cpus */
174 for(j=0; j<trace->channels[i].n_cpus; j++) {
175 char *buf;
176 asprintf(&buf, "%s_%d", trace->channels[i].channel_name, j);
177 result = ustcomm_request_consumer(pid, buf);
178 if(result == -1) {
179 WARN("Failed to request collection for channel %s. Is the daemon available?", trace->channels[i].channel_name);
180 /* continue even if fail */
181 }
182 free(buf);
183 buffers_to_export++;
184 }
185 }
186
187 finish:
188 ltt_unlock_traces();
189 }
190
191 void process_blocked_consumers(void)
192 {
193 int n_fds = 0;
194 struct pollfd *fds;
195 struct blocked_consumer *bc;
196 int idx = 0;
197 char inbuf;
198 int result;
199
200 list_for_each_entry(bc, &blocked_consumers, list) {
201 n_fds++;
202 }
203
204 fds = (struct pollfd *) malloc(n_fds * sizeof(struct pollfd));
205 if(fds == NULL) {
206 ERR("malloc returned NULL");
207 return;
208 }
209
210 list_for_each_entry(bc, &blocked_consumers, list) {
211 fds[idx].fd = bc->fd_producer;
212 fds[idx].events = POLLIN;
213 bc->tmp_poll_idx = idx;
214 idx++;
215 }
216
217 while((result = poll(fds, n_fds, 0)) == -1 && errno == EINTR)
218 /* nothing */;
219 if(result == -1) {
220 PERROR("poll");
221 return;
222 }
223
224 list_for_each_entry(bc, &blocked_consumers, list) {
225 if(fds[bc->tmp_poll_idx].revents) {
226 long consumed_old = 0;
227 char *reply;
228
229 result = read(bc->fd_producer, &inbuf, 1);
230 if(result == -1) {
231 PERROR("read");
232 continue;
233 }
234 if(result == 0) {
235 DBG("PRODUCER END");
236
237 close(bc->fd_producer);
238
239 list_del(&bc->list);
240
241 result = ustcomm_send_reply(&bc->server, "END", &bc->src);
242 if(result < 0) {
243 ERR("ustcomm_send_reply failed");
244 continue;
245 }
246
247 continue;
248 }
249
250 result = ust_buffers_get_subbuf(bc->buf, &consumed_old);
251 if(result == -EAGAIN) {
252 WARN("missed buffer?");
253 continue;
254 }
255 else if(result < 0) {
256 DBG("ust_buffers_get_subbuf: error: %s", strerror(-result));
257 }
258 asprintf(&reply, "%s %ld", "OK", consumed_old);
259 result = ustcomm_send_reply(&bc->server, reply, &bc->src);
260 if(result < 0) {
261 ERR("ustcomm_send_reply failed");
262 free(reply);
263 continue;
264 }
265 free(reply);
266
267 list_del(&bc->list);
268 }
269 }
270
271 }
272
273 void seperate_channel_cpu(const char *channel_and_cpu, char **channel, int *cpu)
274 {
275 const char *sep;
276
277 sep = rindex(channel_and_cpu, '_');
278 if(sep == NULL) {
279 *cpu = -1;
280 sep = channel_and_cpu + strlen(channel_and_cpu);
281 }
282 else {
283 *cpu = atoi(sep+1);
284 }
285
286 asprintf(channel, "%.*s", (int)(sep-channel_and_cpu), channel_and_cpu);
287 }
288
289 static int do_cmd_get_shmid(const char *recvbuf, struct ustcomm_source *src)
290 {
291 int retval = 0;
292 struct ust_trace *trace;
293 char trace_name[] = "auto";
294 int i;
295 char *channel_and_cpu;
296 int found = 0;
297 int result;
298 char *ch_name;
299 int ch_cpu;
300
301 DBG("get_shmid");
302
303 channel_and_cpu = nth_token(recvbuf, 1);
304 if(channel_and_cpu == NULL) {
305 ERR("cannot parse channel");
306 goto end;
307 }
308
309 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
310 if(ch_cpu == -1) {
311 ERR("problem parsing channel name");
312 goto free_short_chan_name;
313 }
314
315 ltt_lock_traces();
316 trace = _ltt_trace_find(trace_name);
317 ltt_unlock_traces();
318
319 if(trace == NULL) {
320 ERR("cannot find trace!");
321 retval = -1;
322 goto free_short_chan_name;
323 }
324
325 for(i=0; i<trace->nr_channels; i++) {
326 struct ust_channel *channel = &trace->channels[i];
327 struct ust_buffer *buf = channel->buf[ch_cpu];
328
329 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
330 char *reply;
331
332 // DBG("the shmid for the requested channel is %d", buf->shmid);
333 // DBG("the shmid for its buffer structure is %d", channel->buf_struct_shmids);
334 asprintf(&reply, "%d %d", buf->shmid, channel->buf_struct_shmids[ch_cpu]);
335
336 result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
337 if(result) {
338 ERR("ustcomm_send_reply failed");
339 free(reply);
340 retval = -1;
341 goto free_short_chan_name;
342 }
343
344 free(reply);
345
346 found = 1;
347 break;
348 }
349 }
350
351 if(!found) {
352 ERR("channel not found (%s)", channel_and_cpu);
353 }
354
355 free_short_chan_name:
356 free(ch_name);
357
358 end:
359 return retval;
360 }
361
362 static int do_cmd_get_n_subbufs(const char *recvbuf, struct ustcomm_source *src)
363 {
364 int retval = 0;
365 struct ust_trace *trace;
366 char trace_name[] = "auto";
367 int i;
368 char *channel_and_cpu;
369 int found = 0;
370 int result;
371 char *ch_name;
372 int ch_cpu;
373
374 DBG("get_n_subbufs");
375
376 channel_and_cpu = nth_token(recvbuf, 1);
377 if(channel_and_cpu == NULL) {
378 ERR("cannot parse channel");
379 goto end;
380 }
381
382 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
383 if(ch_cpu == -1) {
384 ERR("problem parsing channel name");
385 goto free_short_chan_name;
386 }
387
388 ltt_lock_traces();
389 trace = _ltt_trace_find(trace_name);
390 ltt_unlock_traces();
391
392 if(trace == NULL) {
393 ERR("cannot find trace!");
394 retval = -1;
395 goto free_short_chan_name;
396 }
397
398 for(i=0; i<trace->nr_channels; i++) {
399 struct ust_channel *channel = &trace->channels[i];
400
401 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
402 char *reply;
403
404 DBG("the n_subbufs for the requested channel is %d", channel->subbuf_cnt);
405 asprintf(&reply, "%d", channel->subbuf_cnt);
406
407 result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
408 if(result) {
409 ERR("ustcomm_send_reply failed");
410 free(reply);
411 retval = -1;
412 goto free_short_chan_name;
413 }
414
415 free(reply);
416 found = 1;
417 break;
418 }
419 }
420 if(found == 0) {
421 ERR("unable to find channel");
422 }
423
424 free_short_chan_name:
425 free(ch_name);
426
427 end:
428 return retval;
429 }
430
431 static int do_cmd_get_subbuf_size(const char *recvbuf, struct ustcomm_source *src)
432 {
433 int retval = 0;
434 struct ust_trace *trace;
435 char trace_name[] = "auto";
436 int i;
437 char *channel_and_cpu;
438 int found = 0;
439 int result;
440 char *ch_name;
441 int ch_cpu;
442
443 DBG("get_subbuf_size");
444
445 channel_and_cpu = nth_token(recvbuf, 1);
446 if(channel_and_cpu == NULL) {
447 ERR("cannot parse channel");
448 goto end;
449 }
450
451 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
452 if(ch_cpu == -1) {
453 ERR("problem parsing channel name");
454 goto free_short_chan_name;
455 }
456
457 ltt_lock_traces();
458 trace = _ltt_trace_find(trace_name);
459 ltt_unlock_traces();
460
461 if(trace == NULL) {
462 ERR("cannot find trace!");
463 retval = -1;
464 goto free_short_chan_name;
465 }
466
467 for(i=0; i<trace->nr_channels; i++) {
468 struct ust_channel *channel = &trace->channels[i];
469
470 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
471 char *reply;
472
473 DBG("the subbuf_size for the requested channel is %zd", channel->subbuf_size);
474 asprintf(&reply, "%zd", channel->subbuf_size);
475
476 result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
477 if(result) {
478 ERR("ustcomm_send_reply failed");
479 free(reply);
480 retval = -1;
481 goto free_short_chan_name;
482 }
483
484 free(reply);
485 found = 1;
486 break;
487 }
488 }
489 if(found == 0) {
490 ERR("unable to find channel");
491 }
492
493 free_short_chan_name:
494 free(ch_name);
495
496 end:
497 return retval;
498 }
499
500 static unsigned int poweroftwo(unsigned int x)
501 {
502 unsigned int power2 = 1;
503 unsigned int hardcoded = 2147483648; /* FIX max 2^31 */
504
505 if (x < 2)
506 return 2;
507
508 while (power2 < x && power2 < hardcoded)
509 power2 *= 2;
510
511 return power2;
512 }
513
514 static int do_cmd_set_subbuf_size(const char *recvbuf, struct ustcomm_source *src)
515 {
516 char *channel_slash_size;
517 char ch_name[256]="";
518 unsigned int size, power;
519 int retval = 0;
520 struct ust_trace *trace;
521 char trace_name[] = "auto";
522 int i;
523 int found = 0;
524
525 DBG("set_subbuf_size");
526
527 channel_slash_size = nth_token(recvbuf, 1);
528 sscanf(channel_slash_size, "%255[^/]/%u", ch_name, &size);
529
530 if(ch_name == NULL) {
531 ERR("cannot parse channel");
532 goto end;
533 }
534
535 power = poweroftwo(size);
536 if (power != size)
537 WARN("using the next 2^n = %u\n", power);
538
539 ltt_lock_traces();
540 trace = _ltt_trace_find_setup(trace_name);
541 if(trace == NULL) {
542 ERR("cannot find trace!");
543 retval = -1;
544 goto end;
545 }
546
547 for(i = 0; i < trace->nr_channels; i++) {
548 struct ust_channel *channel = &trace->channels[i];
549
550 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
551
552 channel->subbuf_size = power;
553 DBG("the set_subbuf_size for the requested channel is %zd", channel->subbuf_size);
554
555 found = 1;
556 break;
557 }
558 }
559 if(found == 0) {
560 ERR("unable to find channel");
561 }
562
563 end:
564 ltt_unlock_traces();
565 return retval;
566 }
567
568 static int do_cmd_set_subbuf_num(const char *recvbuf, struct ustcomm_source *src)
569 {
570 char *channel_slash_num;
571 char ch_name[256]="";
572 unsigned int num;
573 int retval = 0;
574 struct ust_trace *trace;
575 char trace_name[] = "auto";
576 int i;
577 int found = 0;
578
579 DBG("set_subbuf_num");
580
581 channel_slash_num = nth_token(recvbuf, 1);
582 sscanf(channel_slash_num, "%255[^/]/%u", ch_name, &num);
583
584 if(ch_name == NULL) {
585 ERR("cannot parse channel");
586 goto end;
587 }
588 if (num < 2) {
589 ERR("subbuffer count should be greater than 2");
590 goto end;
591 }
592
593 ltt_lock_traces();
594 trace = _ltt_trace_find_setup(trace_name);
595 if(trace == NULL) {
596 ERR("cannot find trace!");
597 retval = -1;
598 goto end;
599 }
600
601 for(i = 0; i < trace->nr_channels; i++) {
602 struct ust_channel *channel = &trace->channels[i];
603
604 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
605
606 channel->subbuf_cnt = num;
607 DBG("the set_subbuf_cnt for the requested channel is %zd", channel->subbuf_cnt);
608
609 found = 1;
610 break;
611 }
612 }
613 if(found == 0) {
614 ERR("unable to find channel");
615 }
616
617 end:
618 ltt_unlock_traces();
619 return retval;
620 }
621
622 static int do_cmd_get_subbuffer(const char *recvbuf, struct ustcomm_source *src)
623 {
624 int retval = 0;
625 struct ust_trace *trace;
626 char trace_name[] = "auto";
627 int i;
628 char *channel_and_cpu;
629 int found = 0;
630 char *ch_name;
631 int ch_cpu;
632
633 DBG("get_subbuf");
634
635 channel_and_cpu = nth_token(recvbuf, 1);
636 if(channel_and_cpu == NULL) {
637 ERR("cannot parse channel");
638 goto end;
639 }
640
641 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
642 if(ch_cpu == -1) {
643 ERR("problem parsing channel name");
644 goto free_short_chan_name;
645 }
646
647 ltt_lock_traces();
648 trace = _ltt_trace_find(trace_name);
649
650 if(trace == NULL) {
651 int result;
652
653 WARN("Cannot find trace. It was likely destroyed by the user.");
654 result = ustcomm_send_reply(&ustcomm_app.server, "NOTFOUND", src);
655 if(result) {
656 ERR("ustcomm_send_reply failed");
657 retval = -1;
658 goto unlock_traces;
659 }
660
661 goto unlock_traces;
662 }
663
664 for(i=0; i<trace->nr_channels; i++) {
665 struct ust_channel *channel = &trace->channels[i];
666
667 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
668 struct ust_buffer *buf = channel->buf[ch_cpu];
669 struct blocked_consumer *bc;
670
671 found = 1;
672
673 bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer));
674 if(bc == NULL) {
675 ERR("malloc returned NULL");
676 goto unlock_traces;
677 }
678 bc->fd_consumer = src->fd;
679 bc->fd_producer = buf->data_ready_fd_read;
680 bc->buf = buf;
681 bc->src = *src;
682 bc->server = ustcomm_app.server;
683
684 list_add(&bc->list, &blocked_consumers);
685
686 /* Being here is the proof the daemon has mapped the buffer in its
687 * memory. We may now decrement buffers_to_export.
688 */
689 if(uatomic_read(&buf->consumed) == 0) {
690 DBG("decrementing buffers_to_export");
691 buffers_to_export--;
692 }
693
694 break;
695 }
696 }
697 if(found == 0) {
698 ERR("unable to find channel");
699 }
700
701 unlock_traces:
702 ltt_unlock_traces();
703
704 free_short_chan_name:
705 free(ch_name);
706
707 end:
708 return retval;
709 }
710
711 static int do_cmd_put_subbuffer(const char *recvbuf, struct ustcomm_source *src)
712 {
713 int retval = 0;
714 struct ust_trace *trace;
715 char trace_name[] = "auto";
716 int i;
717 char *channel_and_cpu;
718 int found = 0;
719 int result;
720 char *ch_name;
721 int ch_cpu;
722 long consumed_old;
723 char *consumed_old_str;
724 char *endptr;
725 char *reply = NULL;
726
727 DBG("put_subbuf");
728
729 channel_and_cpu = strdup_malloc(nth_token(recvbuf, 1));
730 if(channel_and_cpu == NULL) {
731 ERR("cannot parse channel");
732 retval = -1;
733 goto end;
734 }
735
736 consumed_old_str = strdup_malloc(nth_token(recvbuf, 2));
737 if(consumed_old_str == NULL) {
738 ERR("cannot parse consumed_old");
739 retval = -1;
740 goto free_channel_and_cpu;
741 }
742 consumed_old = strtol(consumed_old_str, &endptr, 10);
743 if(*endptr != '\0') {
744 ERR("invalid value for consumed_old");
745 retval = -1;
746 goto free_consumed_old_str;
747 }
748
749 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
750 if(ch_cpu == -1) {
751 ERR("problem parsing channel name");
752 retval = -1;
753 goto free_short_chan_name;
754 }
755
756 ltt_lock_traces();
757 trace = _ltt_trace_find(trace_name);
758
759 if(trace == NULL) {
760 WARN("Cannot find trace. It was likely destroyed by the user.");
761 result = ustcomm_send_reply(&ustcomm_app.server, "NOTFOUND", src);
762 if(result) {
763 ERR("ustcomm_send_reply failed");
764 retval = -1;
765 goto unlock_traces;
766 }
767
768 goto unlock_traces;
769 }
770
771 for(i=0; i<trace->nr_channels; i++) {
772 struct ust_channel *channel = &trace->channels[i];
773
774 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
775 struct ust_buffer *buf = channel->buf[ch_cpu];
776
777 found = 1;
778
779 result = ust_buffers_put_subbuf(buf, consumed_old);
780 if(result < 0) {
781 WARN("ust_buffers_put_subbuf: error (subbuf=%s)", channel_and_cpu);
782 asprintf(&reply, "%s", "ERROR");
783 }
784 else {
785 DBG("ust_buffers_put_subbuf: success (subbuf=%s)", channel_and_cpu);
786 asprintf(&reply, "%s", "OK");
787 }
788
789 result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
790 if(result) {
791 ERR("ustcomm_send_reply failed");
792 free(reply);
793 retval = -1;
794 goto unlock_traces;
795 }
796
797 free(reply);
798 break;
799 }
800 }
801 if(found == 0) {
802 ERR("unable to find channel");
803 }
804
805 unlock_traces:
806 ltt_unlock_traces();
807 free_short_chan_name:
808 free(ch_name);
809 free_consumed_old_str:
810 free(consumed_old_str);
811 free_channel_and_cpu:
812 free(channel_and_cpu);
813
814 end:
815 return retval;
816 }
817
818 void *listener_main(void *p)
819 {
820 int result;
821
822 DBG("LISTENER");
823
824 for(;;) {
825 char trace_name[] = "auto";
826 char trace_type[] = "ustrelay";
827 char *recvbuf;
828 int len;
829 struct ustcomm_source src;
830
831 process_blocked_consumers();
832
833 result = ustcomm_app_recv_message(&ustcomm_app, &recvbuf, &src, 5);
834 if(result < 0) {
835 WARN("error in ustcomm_app_recv_message");
836 continue;
837 }
838 else if(result == 0) {
839 /* no message */
840 continue;
841 }
842
843 DBG("received a message! it's: %s", recvbuf);
844 len = strlen(recvbuf);
845
846 if(!strcmp(recvbuf, "print_markers")) {
847 print_markers(stderr);
848 }
849 else if(!strcmp(recvbuf, "list_markers")) {
850 char *ptr;
851 size_t size;
852 FILE *fp;
853
854 fp = open_memstream(&ptr, &size);
855 print_markers(fp);
856 fclose(fp);
857
858 result = ustcomm_send_reply(&ustcomm_app.server, ptr, &src);
859
860 free(ptr);
861 }
862 else if(!strcmp(recvbuf, "start")) {
863 /* start is an operation that setups the trace, allocates it and starts it */
864 result = ltt_trace_setup(trace_name);
865 if(result < 0) {
866 ERR("ltt_trace_setup failed");
867 return (void *)1;
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 (void *)1;
874 }
875
876 result = ltt_trace_alloc(trace_name);
877 if(result < 0) {
878 ERR("ltt_trace_alloc failed");
879 return (void *)1;
880 }
881
882 inform_consumer_daemon(trace_name);
883
884 result = ltt_trace_start(trace_name);
885 if(result < 0) {
886 ERR("ltt_trace_start failed");
887 continue;
888 }
889 }
890 else if(!strcmp(recvbuf, "trace_setup")) {
891 DBG("trace setup");
892
893 result = ltt_trace_setup(trace_name);
894 if(result < 0) {
895 ERR("ltt_trace_setup failed");
896 return (void *)1;
897 }
898
899 result = ltt_trace_set_type(trace_name, trace_type);
900 if(result < 0) {
901 ERR("ltt_trace_set_type failed");
902 return (void *)1;
903 }
904 }
905 else if(!strcmp(recvbuf, "trace_alloc")) {
906 DBG("trace alloc");
907
908 result = ltt_trace_alloc(trace_name);
909 if(result < 0) {
910 ERR("ltt_trace_alloc failed");
911 return (void *)1;
912 }
913 inform_consumer_daemon(trace_name);
914 }
915 else if(!strcmp(recvbuf, "trace_create")) {
916 DBG("trace create");
917
918 result = ltt_trace_setup(trace_name);
919 if(result < 0) {
920 ERR("ltt_trace_setup failed");
921 return (void *)1;
922 }
923
924 result = ltt_trace_set_type(trace_name, trace_type);
925 if(result < 0) {
926 ERR("ltt_trace_set_type failed");
927 return (void *)1;
928 }
929 }
930 else if(!strcmp(recvbuf, "trace_start")) {
931 DBG("trace start");
932
933 result = ltt_trace_alloc(trace_name);
934 if(result < 0) {
935 ERR("ltt_trace_alloc failed");
936 return (void *)1;
937 }
938 if(!result) {
939 inform_consumer_daemon(trace_name);
940 }
941
942 result = ltt_trace_start(trace_name);
943 if(result < 0) {
944 ERR("ltt_trace_start failed");
945 continue;
946 }
947 }
948 else if(!strcmp(recvbuf, "trace_stop")) {
949 DBG("trace stop");
950
951 result = ltt_trace_stop(trace_name);
952 if(result < 0) {
953 ERR("ltt_trace_stop failed");
954 return (void *)1;
955 }
956 }
957 else if(!strcmp(recvbuf, "trace_destroy")) {
958
959 DBG("trace destroy");
960
961 result = ltt_trace_destroy(trace_name, 0);
962 if(result < 0) {
963 ERR("ltt_trace_destroy failed");
964 return (void *)1;
965 }
966 }
967 else if(nth_token_is(recvbuf, "get_shmid", 0) == 1) {
968 do_cmd_get_shmid(recvbuf, &src);
969 }
970 else if(nth_token_is(recvbuf, "get_n_subbufs", 0) == 1) {
971 do_cmd_get_n_subbufs(recvbuf, &src);
972 }
973 else if(nth_token_is(recvbuf, "get_subbuf_size", 0) == 1) {
974 do_cmd_get_subbuf_size(recvbuf, &src);
975 }
976 else if(nth_token_is(recvbuf, "load_probe_lib", 0) == 1) {
977 char *libfile;
978
979 libfile = nth_token(recvbuf, 1);
980
981 DBG("load_probe_lib loading %s", libfile);
982
983 free(libfile);
984 }
985 else if(nth_token_is(recvbuf, "get_subbuffer", 0) == 1) {
986 do_cmd_get_subbuffer(recvbuf, &src);
987 }
988 else if(nth_token_is(recvbuf, "put_subbuffer", 0) == 1) {
989 do_cmd_put_subbuffer(recvbuf, &src);
990 }
991 else if(nth_token_is(recvbuf, "set_subbuf_size", 0) == 1) {
992 do_cmd_set_subbuf_size(recvbuf, &src);
993 }
994 else if(nth_token_is(recvbuf, "set_subbuf_num", 0) == 1) {
995 do_cmd_set_subbuf_num(recvbuf, &src);
996 }
997 else if(nth_token_is(recvbuf, "enable_marker", 0) == 1) {
998 char *channel_slash_name = nth_token(recvbuf, 1);
999 char channel_name[256]="";
1000 char marker_name[256]="";
1001
1002 result = sscanf(channel_slash_name, "%255[^/]/%255s", channel_name, marker_name);
1003
1004 if(channel_name == NULL || marker_name == NULL) {
1005 WARN("invalid marker name");
1006 goto next_cmd;
1007 }
1008
1009 result = ltt_marker_connect(channel_name, marker_name, "default");
1010 if(result < 0) {
1011 WARN("could not enable marker; channel=%s, name=%s", channel_name, marker_name);
1012 }
1013 }
1014 else if(nth_token_is(recvbuf, "disable_marker", 0) == 1) {
1015 char *channel_slash_name = nth_token(recvbuf, 1);
1016 char *marker_name;
1017 char *channel_name;
1018
1019 result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
1020
1021 if(marker_name == NULL) {
1022 }
1023
1024 result = ltt_marker_disconnect(channel_name, marker_name, "default");
1025 if(result < 0) {
1026 WARN("could not disable marker; channel=%s, name=%s", channel_name, marker_name);
1027 }
1028 }
1029 else if(nth_token_is(recvbuf, "get_pidunique", 0) == 1) {
1030 char *reply;
1031
1032 asprintf(&reply, "%lld", pidunique);
1033
1034 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
1035 if(result) {
1036 ERR("listener: get_pidunique: ustcomm_send_reply failed");
1037 goto next_cmd;
1038 }
1039
1040 free(reply);
1041 }
1042 // else if(nth_token_is(recvbuf, "get_notifications", 0) == 1) {
1043 // struct ust_trace *trace;
1044 // char trace_name[] = "auto";
1045 // int i;
1046 // char *channel_name;
1047 //
1048 // DBG("get_notifications");
1049 //
1050 // channel_name = strdup_malloc(nth_token(recvbuf, 1));
1051 // if(channel_name == NULL) {
1052 // ERR("put_subbuf_size: cannot parse channel");
1053 // goto next_cmd;
1054 // }
1055 //
1056 // ltt_lock_traces();
1057 // trace = _ltt_trace_find(trace_name);
1058 // ltt_unlock_traces();
1059 //
1060 // if(trace == NULL) {
1061 // ERR("cannot find trace!");
1062 // return (void *)1;
1063 // }
1064 //
1065 // for(i=0; i<trace->nr_channels; i++) {
1066 // struct rchan *rchan = trace->channels[i].trans_channel_data;
1067 // int fd;
1068 //
1069 // if(!strcmp(trace->channels[i].channel_name, channel_name)) {
1070 // struct rchan_buf *rbuf = rchan->buf;
1071 // struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
1072 //
1073 // result = fd = ustcomm_app_detach_client(&ustcomm_app, &src);
1074 // if(result == -1) {
1075 // ERR("ustcomm_app_detach_client failed");
1076 // goto next_cmd;
1077 // }
1078 //
1079 // lttbuf->wake_consumer_arg = (void *) fd;
1080 //
1081 // smp_wmb();
1082 //
1083 // lttbuf->call_wake_consumer = 1;
1084 //
1085 // break;
1086 // }
1087 // }
1088 //
1089 // free(channel_name);
1090 // }
1091 else {
1092 ERR("unable to parse message: %s", recvbuf);
1093 }
1094
1095 next_cmd:
1096 free(recvbuf);
1097 }
1098 }
1099
1100 volatile sig_atomic_t have_listener = 0;
1101
1102 void create_listener(void)
1103 {
1104 #ifdef USE_CLONE
1105 static char listener_stack[16384];
1106 int result;
1107 #else
1108 pthread_t thread;
1109 #endif
1110
1111 if(have_listener) {
1112 WARN("not creating listener because we already had one");
1113 return;
1114 }
1115
1116 #ifdef USE_CLONE
1117 result = clone((int (*)(void *)) listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
1118 if(result == -1) {
1119 perror("clone");
1120 return;
1121 }
1122 #else
1123
1124 pthread_create(&thread, NULL, listener_main, NULL);
1125 #endif
1126
1127 have_listener = 1;
1128 }
1129
1130 static int init_socket(void)
1131 {
1132 return ustcomm_init_app(getpid(), &ustcomm_app);
1133 }
1134
1135 #define AUTOPROBE_DISABLED 0
1136 #define AUTOPROBE_ENABLE_ALL 1
1137 #define AUTOPROBE_ENABLE_REGEX 2
1138 static int autoprobe_method = AUTOPROBE_DISABLED;
1139 static regex_t autoprobe_regex;
1140
1141 static void auto_probe_connect(struct marker *m)
1142 {
1143 int result;
1144
1145 char* concat_name = NULL;
1146 const char *probe_name = "default";
1147
1148 if(autoprobe_method == AUTOPROBE_DISABLED) {
1149 return;
1150 }
1151 else if(autoprobe_method == AUTOPROBE_ENABLE_REGEX) {
1152 result = asprintf(&concat_name, "%s/%s", m->channel, m->name);
1153 if(result == -1) {
1154 ERR("auto_probe_connect: asprintf failed (marker %s/%s)",
1155 m->channel, m->name);
1156 return;
1157 }
1158 if (regexec(&autoprobe_regex, concat_name, 0, NULL, 0)) {
1159 free(concat_name);
1160 return;
1161 }
1162 free(concat_name);
1163 }
1164
1165 result = ltt_marker_connect(m->channel, m->name, probe_name);
1166 if(result && result != -EEXIST)
1167 ERR("ltt_marker_connect (marker = %s/%s, errno = %d)", m->channel, m->name, -result);
1168
1169 DBG("auto connected marker %s (addr: %p) %s to probe default", m->channel, m, m->name);
1170
1171 }
1172
1173 static void __attribute__((constructor)) init()
1174 {
1175 int result;
1176 char* autoprobe_val = NULL;
1177
1178 /* Assign the pidunique, to be able to differentiate the processes with same
1179 * pid, (before and after an exec).
1180 */
1181 pidunique = make_pidunique();
1182
1183 DBG("Tracectl constructor");
1184
1185 result = init_socket();
1186 if(result == -1) {
1187 ERR("init_socket error");
1188 return;
1189 }
1190
1191 create_listener();
1192
1193 autoprobe_val = getenv("UST_AUTOPROBE");
1194 if(autoprobe_val) {
1195 struct marker_iter iter;
1196
1197 DBG("Autoprobe enabled.");
1198
1199 /* Ensure markers are initialized */
1200 //init_markers();
1201
1202 /* Ensure marker control is initialized, for the probe */
1203 init_marker_control();
1204
1205 /* first, set the callback that will connect the
1206 * probe on new markers
1207 */
1208 if(autoprobe_val[0] == '/') {
1209 result = regcomp(&autoprobe_regex, autoprobe_val+1, 0);
1210 if (result) {
1211 char regexerr[150];
1212
1213 regerror(result, &autoprobe_regex, regexerr, sizeof(regexerr));
1214 ERR("cannot parse regex %s (%s), will ignore UST_AUTOPROBE", autoprobe_val, regexerr);
1215 /* don't crash the application just for this */
1216 }
1217 else {
1218 autoprobe_method = AUTOPROBE_ENABLE_REGEX;
1219 }
1220 }
1221 else {
1222 /* just enable all instrumentation */
1223 autoprobe_method = AUTOPROBE_ENABLE_ALL;
1224 }
1225
1226 marker_set_new_marker_cb(auto_probe_connect);
1227
1228 /* Now, connect the probes that were already registered. */
1229 marker_iter_reset(&iter);
1230 marker_iter_start(&iter);
1231
1232 DBG("now iterating on markers already registered");
1233 while(iter.marker) {
1234 DBG("now iterating on marker %s", iter.marker->name);
1235 auto_probe_connect(iter.marker);
1236 marker_iter_next(&iter);
1237 }
1238 }
1239
1240 if(getenv("UST_TRACE")) {
1241 char trace_name[] = "auto";
1242 char trace_type[] = "ustrelay";
1243
1244 DBG("starting early tracing");
1245
1246 /* Ensure marker control is initialized */
1247 init_marker_control();
1248
1249 /* Ensure markers are initialized */
1250 init_markers();
1251
1252 /* Ensure buffers are initialized, for the transport to be available.
1253 * We are about to set a trace type and it will fail without this.
1254 */
1255 init_ustrelay_transport();
1256
1257 /* FIXME: When starting early tracing (here), depending on the
1258 * order of constructors, it is very well possible some marker
1259 * sections are not yet registered. Because of this, some
1260 * channels may not be registered. Yet, we are about to ask the
1261 * daemon to collect the channels. Channels which are not yet
1262 * registered will not be collected.
1263 *
1264 * Currently, in LTTng, there is no way to add a channel after
1265 * trace start. The reason for this is that it induces complex
1266 * concurrency issues on the trace structures, which can only
1267 * be resolved using RCU. This has not been done yet. As a
1268 * workaround, we are forcing the registration of the "ust"
1269 * channel here. This is the only channel (apart from metadata)
1270 * that can be reliably used in early tracing.
1271 *
1272 * Non-early tracing does not have this problem and can use
1273 * arbitrary channel names.
1274 */
1275 ltt_channels_register("ust");
1276
1277 result = ltt_trace_setup(trace_name);
1278 if(result < 0) {
1279 ERR("ltt_trace_setup failed");
1280 return;
1281 }
1282
1283 result = ltt_trace_set_type(trace_name, trace_type);
1284 if(result < 0) {
1285 ERR("ltt_trace_set_type failed");
1286 return;
1287 }
1288
1289 result = ltt_trace_alloc(trace_name);
1290 if(result < 0) {
1291 ERR("ltt_trace_alloc failed");
1292 return;
1293 }
1294
1295 result = ltt_trace_start(trace_name);
1296 if(result < 0) {
1297 ERR("ltt_trace_start failed");
1298 return;
1299 }
1300
1301 /* Do this after the trace is started in order to avoid creating confusion
1302 * if the trace fails to start. */
1303 inform_consumer_daemon(trace_name);
1304 }
1305
1306
1307 return;
1308
1309 /* should decrementally destroy stuff if error */
1310
1311 }
1312
1313 /* This is only called if we terminate normally, not with an unhandled signal,
1314 * so we cannot rely on it. However, for now, LTTV requires that the header of
1315 * the last sub-buffer contain a valid end time for the trace. This is done
1316 * automatically only when the trace is properly stopped.
1317 *
1318 * If the traced program crashed, it is always possible to manually add the
1319 * right value in the header, or to open the trace in text mode.
1320 *
1321 * FIXME: Fix LTTV so it doesn't need this.
1322 */
1323
1324 static void destroy_traces(void)
1325 {
1326 int result;
1327
1328 /* if trace running, finish it */
1329
1330 DBG("destructor stopping traces");
1331
1332 result = ltt_trace_stop("auto");
1333 if(result == -1) {
1334 ERR("ltt_trace_stop error");
1335 }
1336
1337 result = ltt_trace_destroy("auto", 0);
1338 if(result == -1) {
1339 ERR("ltt_trace_destroy error");
1340 }
1341 }
1342
1343 static int trace_recording(void)
1344 {
1345 int retval = 0;
1346 struct ust_trace *trace;
1347
1348 ltt_lock_traces();
1349
1350 list_for_each_entry(trace, &ltt_traces.head, list) {
1351 if(trace->active) {
1352 retval = 1;
1353 break;
1354 }
1355 }
1356
1357 ltt_unlock_traces();
1358
1359 return retval;
1360 }
1361
1362 #if 0
1363 static int have_consumer(void)
1364 {
1365 return !list_empty(&blocked_consumers);
1366 }
1367 #endif
1368
1369 int restarting_usleep(useconds_t usecs)
1370 {
1371 struct timespec tv;
1372 int result;
1373
1374 tv.tv_sec = 0;
1375 tv.tv_nsec = usecs * 1000;
1376
1377 do {
1378 result = nanosleep(&tv, &tv);
1379 } while(result == -1 && errno == EINTR);
1380
1381 return result;
1382 }
1383
1384 /* This destructor keeps the process alive for a few seconds in order
1385 * to leave time to ustd to connect to its buffers. This is necessary
1386 * for programs whose execution is very short. It is also useful in all
1387 * programs when tracing is started close to the end of the program
1388 * execution.
1389 *
1390 * FIXME: For now, this only works for the first trace created in a
1391 * process.
1392 */
1393
1394 static void __attribute__((destructor)) keepalive()
1395 {
1396 if(trace_recording() && buffers_to_export) {
1397 int total = 0;
1398 DBG("Keeping process alive for consumer daemon...");
1399 while(buffers_to_export) {
1400 const int interv = 200000;
1401 restarting_usleep(interv);
1402 total += interv;
1403
1404 if(total >= 3000000) {
1405 WARN("non-consumed buffers remaining after wait limit; not waiting anymore");
1406 break;
1407 }
1408 }
1409 DBG("Finally dying...");
1410 }
1411
1412 destroy_traces();
1413
1414 ustcomm_fini_app(&ustcomm_app, 0);
1415 }
1416
1417 void ust_potential_exec(void)
1418 {
1419 trace_mark(ust, potential_exec, MARK_NOARGS);
1420
1421 DBG("test");
1422
1423 keepalive();
1424 }
1425
1426 /* Notify ust that there was a fork. This needs to be called inside
1427 * the new process, anytime a process whose memory is not shared with
1428 * the parent is created. If this function is not called, the events
1429 * of the new process will not be collected.
1430 *
1431 * Signals should be disabled before the fork and reenabled only after
1432 * this call in order to guarantee tracing is not started before ust_fork()
1433 * sanitizes the new process.
1434 */
1435
1436 static void ust_fork(void)
1437 {
1438 struct blocked_consumer *bc;
1439 struct blocked_consumer *deletable_bc = NULL;
1440 int result;
1441
1442 /* FIXME: technically, the locks could have been taken before the fork */
1443 DBG("ust: forking");
1444
1445 /* break lock if necessary */
1446 ltt_unlock_traces();
1447
1448 ltt_trace_stop("auto");
1449 ltt_trace_destroy("auto", 1);
1450 /* Delete all active connections */
1451 ustcomm_close_all_connections(&ustcomm_app.server);
1452
1453 /* Delete all blocked consumers */
1454 list_for_each_entry(bc, &blocked_consumers, list) {
1455 close(bc->fd_producer);
1456 close(bc->fd_consumer);
1457 free(deletable_bc);
1458 deletable_bc = bc;
1459 list_del(&bc->list);
1460 }
1461
1462 /* free app, keeping socket file */
1463 ustcomm_fini_app(&ustcomm_app, 1);
1464
1465 buffers_to_export = 0;
1466 have_listener = 0;
1467 init_socket();
1468 create_listener();
1469 ltt_trace_setup("auto");
1470 result = ltt_trace_set_type("auto", "ustrelay");
1471 if(result < 0) {
1472 ERR("ltt_trace_set_type failed");
1473 return;
1474 }
1475
1476 ltt_trace_alloc("auto");
1477 ltt_trace_start("auto");
1478 inform_consumer_daemon("auto");
1479 }
1480
1481 void ust_before_fork(ust_fork_info_t *fork_info)
1482 {
1483 /* Disable signals. This is to avoid that the child
1484 * intervenes before it is properly setup for tracing. It is
1485 * safer to disable all signals, because then we know we are not
1486 * breaking anything by restoring the original mask.
1487 */
1488 sigset_t all_sigs;
1489 int result;
1490
1491 /* FIXME:
1492 - only do this if tracing is active
1493 */
1494
1495 /* Disable signals */
1496 sigfillset(&all_sigs);
1497 result = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs);
1498 if(result == -1) {
1499 PERROR("sigprocmask");
1500 return;
1501 }
1502 }
1503
1504 /* Don't call this function directly in a traced program */
1505 static void ust_after_fork_common(ust_fork_info_t *fork_info)
1506 {
1507 int result;
1508
1509 /* Restore signals */
1510 result = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL);
1511 if(result == -1) {
1512 PERROR("sigprocmask");
1513 return;
1514 }
1515 }
1516
1517 void ust_after_fork_parent(ust_fork_info_t *fork_info)
1518 {
1519 /* Reenable signals */
1520 ust_after_fork_common(fork_info);
1521 }
1522
1523 void ust_after_fork_child(ust_fork_info_t *fork_info)
1524 {
1525 /* First sanitize the child */
1526 ust_fork();
1527
1528 /* Then reenable interrupts */
1529 ust_after_fork_common(fork_info);
1530 }
1531
This page took 0.063111 seconds and 5 git commands to generate.