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