Fix lttctl flight recorder wait for daemon (temp fix)
[ltt-control.git] / lttctl / lttctl.c
CommitLineData
2727692a 1/* lttctl
2 *
3 * Linux Trace Toolkit Control
4 *
ed2849af 5 * Small program that controls LTTng through liblttctl.
b1f29379 6 *
7 * Copyright 2008 FUJITSU
8 * Zhao Lei <zhaolei@cn.fujitsu.com>
9 * Gui Jianfeng <guijianfeng@cn.fujitsu.com>
ed2849af
MD
10 * Copyright 2009-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2727692a 25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31#include <liblttctl/lttctl.h>
32#include <errno.h>
33#include <stdio.h>
34#include <stdlib.h>
2727692a 35#include <sys/wait.h>
36#include <unistd.h>
2727692a 37#include <string.h>
a9c10be2 38#include <limits.h>
c928825d 39#define _GNU_SOURCE
40#include <getopt.h>
41
42#define OPT_MAX (1024)
43#define OPT_NAMELEN (256)
44#define OPT_VALSTRINGLEN (256)
45
b1f29379 46enum opt_type {
47 CHANNEL,
48};
49
50struct channel_option {
51 char chan_name[OPT_NAMELEN];
52 int enable;
53 int overwrite;
54 int bufnum;
55 int bufsize;
8d5607b4 56 int switch_timer;
2727692a 57};
58
c928825d 59struct lttctl_option {
c928825d 60 union {
b1f29379 61 struct channel_option chan_opt;
62 } opt_mode;
63 enum opt_type type;
64 struct lttctl_option *next;
c928825d 65};
66
b1f29379 67struct lttctl_option *opt_head, *last_opt;
68
c928825d 69static int opt_create;
70static int opt_destroy;
71static int opt_start;
72static int opt_pause;
73static int opt_help;
74static const char *opt_transport;
c928825d 75static const char *opt_write;
76static int opt_append;
77static unsigned int opt_dump_threads;
a9c10be2 78static char channel_root_default[PATH_MAX];
c928825d 79static const char *opt_channel_root;
80static const char *opt_tracename;
2727692a 81
2727692a 82/* Args :
83 *
84 */
c928825d 85static void show_arguments(void)
2727692a 86{
c928825d 87 printf("Linux Trace Toolkit Trace Control " VERSION"\n");
88 printf("\n");
89 printf("Usage: lttctl [OPTION]... [TRACENAME]\n");
90 printf("\n");
91 printf("Examples:\n");
92 printf(" lttctl -c trace1 "
93 "# Create a trace named trace1.\n");
94 printf(" lttctl -s trace1 "
95 "# start a trace named trace1.\n");
96 printf(" lttctl -p trace1 "
97 "# pause a trace named trace1.\n");
98 printf(" lttctl -d trace1 "
99 "# Destroy a trace named trace1.\n");
100 printf(" lttctl -C -w /tmp/trace1 trace1 "
101 "# Create a trace named trace1, start it and\n"
102 " "
103 "# write non-overwrite channels' data to\n"
104 " "
105 "# /tmp/trace1, debugfs must be mounted for\n"
106 " "
107 "# auto-find\n");
108 printf(" lttctl -D -w /tmp/trace1 trace1 "
109 "# Pause and destroy a trace named trace1 and\n"
110 " "
111 "# write overwrite channels' data to\n"
112 " "
113 "# /tmp/trace1, debugfs must be mounted for\n"
114 " "
115 "# auto-find\n");
116 printf("\n");
117 printf(" Basic options:\n");
118 printf(" -c, --create\n");
119 printf(" Create a trace.\n");
120 printf(" -d, --destroy\n");
121 printf(" Destroy a trace.\n");
122 printf(" -s, --start\n");
123 printf(" Start a trace.\n");
124 printf(" -p, --pause\n");
125 printf(" Pause a trace.\n");
126 printf(" -h, --help\n");
127 printf(" Show this help.\n");
2727692a 128 printf("\n");
c928825d 129 printf(" Advanced options:\n");
130 printf(" --transport TRANSPORT\n");
07d97665 131 printf(" Set trace's transport. (ex. relay-locked or relay)\n");
c928825d 132 printf(" -o, --option OPTION\n");
133 printf(" Set options, following operations are supported:\n");
134 printf(" channel.<channelname>.enable=\n");
135 printf(" channel.<channelname>.overwrite=\n");
136 printf(" channel.<channelname>.bufnum=\n");
c68a7692 137 printf(" channel.<channelname>.bufsize= (in bytes, rounded to "
138 "next power of 2)\n");
c928825d 139 printf(" <channelname> can be set to all for all channels\n");
8d5607b4
MD
140 printf(" channel.<channelname>.switch_timer= (timer interval in "
141 "ms)\n");
c928825d 142 printf("\n");
143 printf(" Integration options:\n");
144 printf(" -C, --create_start\n");
145 printf(" Create and start a trace.\n");
146 printf(" -D, --pause_destroy\n");
147 printf(" Pause and destroy a trace.\n");
148 printf(" -w, --write PATH\n");
149 printf(" Path for write trace datas.\n");
150 printf(" For -c, -C, -d, -D options\n");
151 printf(" -a, --append\n");
152 printf(" Append to trace, For -w option\n");
153 printf(" -n, --dump_threads NUMBER\n");
154 printf(" Number of lttd threads, For -w option\n");
155 printf(" --channel_root PATH\n");
156 printf(" Set channels root path, For -w option."
157 " (ex. /mnt/debugfs/ltt)\n");
2727692a 158 printf("\n");
323ef0a3
MD
159 printf(" Environment variables:\n");
160 printf(" LTT_DAEMON\n");
161 printf(" Complete path to the lttd binary (needs to be\n");
162 printf(" specified if different than package build prefix).\n");
163 printf("\n");
2727692a 164}
165
c928825d 166/*
167 * Separate option name to 3 fields
168 * Ex:
169 * Input: name = channel.cpu.bufsize
170 * Output: name1 = channel
171 * name2 = cpu
172 * name3 = bufsize
173 * Ret: 0 on success
174 * 1 on fail
175 *
176 * Note:
177 * Make sure that name1~3 longer than OPT_NAMELEN.
178 * name1~3 can be NULL to discard value
179 *
180 */
181static int separate_opt(const char *name, char *name1, char *name2, char *name3)
182{
183 char *p;
184
185 if (!name)
186 return 1;
187
188 /* segment1 */
189 p = strchr(name, '.');
190 if (!p)
191 return 1;
192 if (p - name >= OPT_NAMELEN)
193 return 1;
194 if (name1) {
195 memcpy(name1, name, p - name);
196 name1[p - name] = 0;
197 }
198 name = p + 1;
199
200 /* segment2 */
201 p = strchr(name, '.');
202 if (!p)
203 return 1;
204 if (p - name >= OPT_NAMELEN)
205 return 1;
206 if (name2) {
207 memcpy(name2, name, p - name);
208 name2[p - name] = 0;
209 }
210 name = p + 1;
211
212 /* segment3 */
213 if (strlen(name) >= OPT_NAMELEN)
214 return 1;
215 if (name3)
216 strcpy(name3, name);
217
218 return 0;
219}
220
b1f29379 221static void init_channel_opt(struct channel_option *opt, char *opt_name)
c928825d 222{
b1f29379 223 if (opt && opt_name) {
224 opt->enable = -1;
225 opt->overwrite = -1;
226 opt->bufnum = -1;
227 opt->bufsize = -1;
8d5607b4 228 opt->switch_timer = -1;
b1f29379 229 strcpy(opt->chan_name, opt_name);
c928825d 230 }
c928825d 231}
232
b1f29379 233static struct lttctl_option *find_insert_channel_opt(char *opt_name)
c928825d 234{
b1f29379 235 struct lttctl_option *iter, *new_opt;
236
237 if (!opt_head) {
238 opt_head = (struct lttctl_option *)malloc(sizeof(struct lttctl_option));
239 init_channel_opt(&opt_head->opt_mode.chan_opt, opt_name);
240 opt_head->type = CHANNEL;
241 opt_head->next = NULL;
242 last_opt = opt_head;
243 return opt_head;
244 }
c928825d 245
b1f29379 246 for (iter = opt_head; iter; iter = iter->next) {
247 if (iter->type != CHANNEL)
248 continue;
249 if (!strcmp(iter->opt_mode.chan_opt.chan_name, opt_name))
250 return iter;
c928825d 251 }
252
b1f29379 253 new_opt = (struct lttctl_option *)malloc(sizeof(struct lttctl_option));
254 init_channel_opt(&new_opt->opt_mode.chan_opt, opt_name);
255 new_opt->type = CHANNEL;
256 new_opt->next = NULL;
257 last_opt->next = new_opt;
258 last_opt = new_opt;
259 return new_opt;
c928825d 260}
261
b1f29379 262int set_channel_opt(struct channel_option *opt, char *opt_name, char *opt_valstr)
c928825d 263{
b1f29379 264 int opt_val, ret;
c928825d 265
b1f29379 266 if (!strcmp("enable", opt_name)) {
267 if (opt_valstr[1] != 0) {
268 return -EINVAL;
269 }
270 if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
271 || opt_valstr[0] == '1')
272 opt_val = 1;
273 else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
274 || opt_valstr[0] == '0')
275 opt_val = 0;
276 else {
277 return -EINVAL;
278 }
c928825d 279
b1f29379 280 opt->enable = opt_val;
281 return 0;
282 } else if (!strcmp("overwrite", opt_name)) {
283 if (opt_valstr[1] != 0) {
284 return -EINVAL;
285 }
286 if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
287 || opt_valstr[0] == '1')
288 opt_val = 1;
289 else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
290 || opt_valstr[0] == '0')
291 opt_val = 0;
292 else {
293 return -EINVAL;
294 }
c928825d 295
b1f29379 296 opt->overwrite = opt_val;
297 return 0;
c928825d 298
b1f29379 299 } else if (!strcmp("bufnum", opt_name)) {
300 ret = sscanf(opt_valstr, "%d", &opt_val);
301 if (ret != 1 || opt_val < 0) {
302 return -EINVAL;
303 }
304
305 opt->bufnum = opt_val;
306 return 0;
307 } else if (!strcmp("bufsize", opt_name)) {
308 ret = sscanf(opt_valstr, "%d", &opt_val);
309 if (ret != 1 || opt_val < 0) {
310 return -EINVAL;
311 }
312
313 opt->bufsize = opt_val;
314 return 0;
8d5607b4
MD
315 } else if (!strcmp("switch_timer", opt_name)) {
316 ret = sscanf(opt_valstr, "%d", &opt_val);
317 if (ret != 1 || opt_val < 0) {
318 return -EINVAL;
319 }
320
321 opt->switch_timer = opt_val;
322 return 0;
b1f29379 323 } else {
324 return -EINVAL;
c928825d 325 }
326
c928825d 327}
328
329static int parst_opt(const char *optarg)
330{
331 int ret;
332 char opt_name[OPT_NAMELEN * 3];
333 char opt_valstr[OPT_VALSTRINGLEN];
334 char *p;
335
336 char name1[OPT_NAMELEN];
337 char name2[OPT_NAMELEN];
338 char name3[OPT_NAMELEN];
339
c928825d 340 int opt_intval;
b1f29379 341 int opt_val;
c928825d 342 unsigned int opt_uintval;
b1f29379 343 struct lttctl_option *opt;
c928825d 344
345 if (!optarg) {
346 fprintf(stderr, "Option empty\n");
347 return -EINVAL;
348 }
349
350 /* Get option name and val_str */
351 p = strchr(optarg, '=');
352 if (!p) {
353 fprintf(stderr, "Option format error: %s\n", optarg);
354 return -EINVAL;
355 }
356
357 if (p - optarg >= sizeof(opt_name)/sizeof(opt_name[0])) {
358 fprintf(stderr, "Option name too long: %s\n", optarg);
359 return -EINVAL;
360 }
361
362 if (strlen(p+1) >= OPT_VALSTRINGLEN) {
363 fprintf(stderr, "Option value too long: %s\n", optarg);
364 return -EINVAL;
365 }
366
367 memcpy(opt_name, optarg, p - optarg);
368 opt_name[p - optarg] = 0;
369 strcpy(opt_valstr, p+1);
370
371 /* separate option name into 3 fields */
372 ret = separate_opt(opt_name, name1, name2, name3);
373 if (ret != 0) {
b1f29379 374 fprintf(stderr, "Option name error1: %s\n", optarg);
c928825d 375 return -EINVAL;
376 }
b1f29379 377
378 if (!strcmp("channel", name1)) {
379 opt = find_insert_channel_opt(name2);
380 if ((ret = set_channel_opt(&opt->opt_mode.chan_opt,
381 name3, opt_valstr) != 0)) {
382 fprintf(stderr, "Option name error2: %s\n", optarg);
383 return ret;
c928825d 384 }
b1f29379 385 } else {
386 fprintf(stderr, "Option name error3: %s\n", optarg);
c928825d 387 return -EINVAL;
388 }
b1f29379 389
390 return 0;
c928825d 391}
392
2727692a 393/* parse_arguments
394 *
395 * Parses the command line arguments.
396 *
397 * Returns -1 if the arguments were correct, but doesn't ask for program
398 * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
399 */
c928825d 400static int parse_arguments(int argc, char **argv)
2727692a 401{
402 int ret = 0;
b1f29379 403
c928825d 404 static struct option longopts[] = {
405 {"create", no_argument, NULL, 'c'},
406 {"destroy", no_argument, NULL, 'd'},
407 {"start", no_argument, NULL, 's'},
408 {"pause", no_argument, NULL, 'p'},
409 {"help", no_argument, NULL, 'h'},
410 {"transport", required_argument, NULL, 2},
411 {"option", required_argument, NULL, 'o'},
412 {"create_start", no_argument, NULL, 'C'},
413 {"pause_destroy", no_argument, NULL, 'D'},
414 {"write", required_argument, NULL, 'w'},
415 {"append", no_argument, NULL, 'a'},
416 {"dump_threads", required_argument, NULL, 'n'},
417 {"channel_root", required_argument, NULL, 3},
418 { NULL, 0, NULL, 0 },
419 };
420
421 /*
422 * Enable all channels in default
423 * To make novice users happy
424 */
425 parst_opt("channel.all.enable=1");
426
427 opterr = 1; /* Print error message on getopt_long */
428 while (1) {
429 int c;
430 c = getopt_long(argc, argv, "cdspho:CDw:an:", longopts, NULL);
431 if (-1 == c) {
432 /* parse end */
433 break;
2727692a 434 }
c928825d 435 switch (c) {
436 case 'c':
437 opt_create = 1;
438 break;
439 case 'd':
440 opt_destroy = 1;
441 break;
442 case 's':
443 opt_start = 1;
444 break;
445 case 'p':
446 opt_pause = 1;
447 break;
448 case 'h':
449 opt_help = 1;
450 break;
451 case 2:
452 if (!opt_transport) {
453 opt_transport = optarg;
454 } else {
455 fprintf(stderr,
456 "Please specify only 1 transport\n");
457 return -EINVAL;
458 }
459 break;
460 case 'o':
461 ret = parst_opt(optarg);
462 if (ret)
463 return ret;
464 break;
465 case 'C':
466 opt_create = 1;
467 opt_start = 1;
468 break;
469 case 'D':
470 opt_pause = 1;
471 opt_destroy = 1;
472 break;
473 case 'w':
474 if (!opt_write) {
475 opt_write = optarg;
476 } else {
477 fprintf(stderr,
478 "Please specify only 1 write dir\n");
479 return -EINVAL;
480 }
481 break;
482 case 'a':
483 opt_append = 1;
484 break;
485 case 'n':
486 if (opt_dump_threads) {
487 fprintf(stderr,
488 "Please specify only 1 dump threads\n");
489 return -EINVAL;
490 }
491
492 ret = sscanf(optarg, "%u", &opt_dump_threads);
493 if (ret != 1) {
494 fprintf(stderr,
495 "Dump threads not positive number\n");
496 return -EINVAL;
497 }
498 break;
499 case 3:
500 if (!opt_channel_root) {
501 opt_channel_root = optarg;
502 } else {
503 fprintf(stderr,
504 "Please specify only 1 channel root\n");
505 return -EINVAL;
506 }
507 break;
508 case '?':
509 return -EINVAL;
510 default:
511 break;
512 };
513 };
514
515 /* Don't check args when user needs help */
516 if (opt_help)
517 return 0;
518
519 /* Get tracename */
520 if (optind < argc - 1) {
521 fprintf(stderr, "Please specify only 1 trace name\n");
522 return -EINVAL;
523 }
524 if (optind > argc - 1) {
525 fprintf(stderr, "Please specify trace name\n");
526 return -EINVAL;
527 }
528 opt_tracename = argv[optind];
529
530 /*
531 * Check arguments
532 */
533 if (!opt_create && !opt_start && !opt_destroy && !opt_pause) {
534 fprintf(stderr,
535 "Please specify a option of "
536 "create, destroy, start, or pause\n");
537 return -EINVAL;
2727692a 538 }
539
c928825d 540 if ((opt_create || opt_start) && (opt_destroy || opt_pause)) {
541 fprintf(stderr,
542 "Create and start conflict with destroy and pause\n");
543 return -EINVAL;
2727692a 544 }
c928825d 545
546 if (opt_create) {
547 if (!opt_transport)
548 opt_transport = "relay";
2727692a 549 }
550
c928825d 551 if (opt_transport) {
552 if (!opt_create) {
553 fprintf(stderr,
554 "Transport option must be combine with create"
555 " option\n");
556 return -EINVAL;
557 }
2727692a 558 }
559
c928825d 560 if (opt_write) {
561 if (!opt_create && !opt_destroy) {
562 fprintf(stderr,
563 "Write option must be combine with create or"
564 " destroy option\n");
565 return -EINVAL;
2727692a 566 }
c928825d 567
568 if (!opt_channel_root)
a9c10be2 569 if (getdebugfsmntdir(channel_root_default) == 0) {
570 strcat(channel_root_default, "/ltt");
c928825d 571 opt_channel_root = channel_root_default;
354b34fd 572 } else {
573 fprintf(stderr,
574 "Channel_root is necessary for -w"
575 " option, but neither --channel_root"
576 " option\n"
577 "specified, nor debugfs's mount dir"
578 " found, mount debugfs also failed\n");
579 return -EINVAL;
a9c10be2 580 }
c928825d 581
582 if (opt_dump_threads == 0)
583 opt_dump_threads = 1;
2727692a 584 }
585
c928825d 586 if (opt_append) {
587 if (!opt_write) {
588 fprintf(stderr,
589 "Append option must be combine with write"
590 " option\n");
591 return -EINVAL;
592 }
593 }
594
595 if (opt_dump_threads) {
596 if (!opt_write) {
597 fprintf(stderr,
598 "Dump_threads option must be combine with write"
599 " option\n");
600 return -EINVAL;
601 }
602 }
603
604 if (opt_channel_root) {
605 if (!opt_write) {
606 fprintf(stderr,
607 "Channel_root option must be combine with write"
608 " option\n");
609 return -EINVAL;
610 }
611 }
612
613 return 0;
2727692a 614}
b1f29379 615
c928825d 616static void show_info(void)
2727692a 617{
15061ecb 618 printf("Linux Trace Toolkit Trace Control " VERSION"\n");
2727692a 619 printf("\n");
c928825d 620 if (opt_tracename != NULL) {
621 printf("Controlling trace : %s\n", opt_tracename);
900b24a9 622 printf("\n");
623 }
2727692a 624}
625
b1f29379 626static int lttctl_channel_setup(struct channel_option *opt)
627{
628 int ret;
629
630 if (opt->enable != -1) {
631 if ((ret = lttctl_set_channel_enable(opt_tracename,
632 opt->chan_name,
633 opt->enable)) != 0)
634 return ret;
635 }
636 if (opt->overwrite != -1) {
637 if ((ret = lttctl_set_channel_overwrite(opt_tracename,
638 opt->chan_name,
639 opt->overwrite)) != 0)
640 return ret;
641 }
642 if (opt->bufnum != -1) {
643 if ((ret = lttctl_set_channel_subbuf_num(opt_tracename,
644 opt->chan_name,
645 opt->bufnum)) != 0)
646 return ret;
647 }
648 if (opt->bufsize != -1) {
649 if ((ret = lttctl_set_channel_subbuf_size(opt_tracename,
650 opt->chan_name,
651 opt->bufsize)) != 0)
652 return ret;
653 }
8d5607b4
MD
654 if (opt->switch_timer != -1) {
655 if ((ret = lttctl_set_channel_switch_timer(opt_tracename,
656 opt->chan_name, opt->switch_timer)) != 0)
657 return ret;
658 }
b1f29379 659
660 return 0;
661}
662
c928825d 663static int lttctl_create_trace(void)
2727692a 664{
2727692a 665 int ret;
c928825d 666 int i;
b1f29379 667 struct lttctl_option *opt;
c928825d 668
669 ret = lttctl_setup_trace(opt_tracename);
670 if (ret)
671 goto setup_trace_fail;
672
b1f29379 673 for (opt = opt_head; opt; opt = opt->next) {
674 if (opt->type != CHANNEL)
c928825d 675 continue;
b1f29379 676 ret = lttctl_channel_setup(&opt->opt_mode.chan_opt);
677 if (ret)
678 goto set_option_fail;;
2727692a 679 }
680
c928825d 681 ret = lttctl_set_trans(opt_tracename, opt_transport);
682 if (ret)
683 goto set_option_fail;
684
685 ret = lttctl_alloc_trace(opt_tracename);
686 if (ret)
687 goto alloc_trace_fail;
2727692a 688
689 return 0;
690
c928825d 691alloc_trace_fail:
692set_option_fail:
693 lttctl_destroy_trace(opt_tracename);
694setup_trace_fail:
2727692a 695 return ret;
696}
697
c928825d 698/*
0d45cf3d 699 * Start a lttd daemon to write trace data
c928825d 700 * Dump overwrite channels on overwrite!=0
701 * Dump normal(non-overwrite) channels on overwrite=0
702 *
0d45cf3d
MD
703 * When called for overwrite mode, wait for lttd to return, so we are sure that
704 * trace session teardown is not executed before lttd can grab the buffer data.
705 *
c928825d 706 * ret: 0 on success
707 * !0 on fail
708 */
709static int lttctl_daemon(int overwrite)
89565b43 710{
89565b43 711 pid_t pid;
c928825d 712 int status;
89565b43 713
714 pid = fork();
c928825d 715 if (pid < 0) {
716 perror("Error in forking for lttd daemon");
717 return errno;
718 }
89565b43 719
c928825d 720 if (pid == 0) {
721 /* child */
722 char *argv[16];
723 int argc = 0;
724 char channel_path[PATH_MAX];
725 char thread_num[16];
726
727 /* prog path */
728 argv[argc] = getenv("LTT_DAEMON");
729 if (argv[argc] == NULL)
730 argv[argc] = PACKAGE_BIN_DIR "/lttd";
731 argc++;
732
733 /* -t option */
734 argv[argc] = "-t";
735 argc++;
736 /*
737 * we allow modify of opt_write's content in new process
738 * for get rid of warning of assign char * to const char *
739 */
740 argv[argc] = (char *)opt_write;
741 argc++;
742
743 /* -c option */
744 strcpy(channel_path, opt_channel_root);
745 strcat(channel_path, "/");
746 strcat(channel_path, opt_tracename);
747 argv[argc] = "-c";
748 argc++;
749 argv[argc] = channel_path;
750 argc++;
751
752 /* -N option */
753 sprintf(thread_num, "%u", opt_dump_threads);
754 argv[argc] = "-N";
755 argc++;
756 argv[argc] = thread_num;
757 argc++;
758
759 /* -a option */
760 if (opt_append) {
761 argv[argc] = "-a";
762 argc++;
89565b43 763 }
764
c928825d 765 /* -d option */
635683d7
MD
766 argv[argc] = "-d";
767 argc++;
89565b43 768
c928825d 769 /* overwrite option */
770 if (overwrite) {
771 argv[argc] = "-f";
772 argc++;
773 } else {
774 argv[argc] = "-n";
775 argc++;
89565b43 776 }
89565b43 777
c928825d 778 argv[argc] = NULL;
89565b43 779
c928825d 780 execvp(argv[0], argv);
89565b43 781
c928825d 782 perror("Error in executing the lttd daemon");
783 exit(errno);
784 }
89565b43 785
c928825d 786 /* parent */
787 if (waitpid(pid, &status, 0) == -1) {
788 perror("Error in waitpid\n");
789 return errno;
790 }
89565b43 791
c928825d 792 if (!WIFEXITED(status)) {
793 fprintf(stderr, "lttd process interrupted\n");
794 return status;
795 }
796
797 if (WEXITSTATUS(status))
798 fprintf(stderr, "lttd process running failed\n");
89565b43 799
635683d7
MD
800 /*
801 * FIXME
802 * This is a temporary hack to ensure that the lttd daemon grabs
803 * handles on the debugfs buffer files before we destroy the trace
804 * session. Properly handling this will imply separating the "flush"
805 * from the "destroy" operation at kernel-level in LTTng.
806 */
807 if (overwrite)
808 sleep(2);
809
c928825d 810 return WEXITSTATUS(status);
811}
812
813int main(int argc, char **argv)
2727692a 814{
815 int ret;
c928825d 816
2727692a 817 ret = parse_arguments(argc, argv);
c928825d 818 /* If user needs show help, we disregard other options */
819 if (opt_help) {
820 show_arguments();
821 return 0;
822 }
2727692a 823
c928825d 824 /* exit program if arguments wrong */
825 if (ret)
826 return 1;
2727692a 827
828 show_info();
c928825d 829
830 ret = lttctl_init();
831 if (ret != 0)
832 return ret;
833
834 if (opt_create) {
835 printf("lttctl: Creating trace\n");
836 ret = lttctl_create_trace();
837 if (ret)
838 goto op_fail;
839
840 if (opt_write) {
841 printf("lttctl: Forking lttd\n");
842 ret = lttctl_daemon(0);
843 if (ret)
844 goto op_fail;
845 }
846 }
847
848 if (opt_start) {
849 printf("lttctl: Starting trace\n");
850 ret = lttctl_start(opt_tracename);
851 if (ret)
852 goto op_fail;
853 }
854
855 if (opt_pause) {
856 printf("lttctl: Pausing trace\n");
857 ret = lttctl_pause(opt_tracename);
858 if (ret)
859 goto op_fail;
2727692a 860 }
861
c928825d 862 if (opt_destroy) {
863 if (opt_write) {
864 printf("lttctl: Forking lttd\n");
865 ret = lttctl_daemon(1);
866 if (ret)
867 goto op_fail;
868 }
869
870 printf("lttctl: Destroying trace\n");
871 ret = lttctl_destroy_trace(opt_tracename);
872 if (ret)
873 goto op_fail;
874 }
875
876op_fail:
877 lttctl_destroy();
878
2727692a 879 return ret;
880}
This page took 0.084244 seconds and 4 git commands to generate.