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