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