From f248b7d81143c5ff7b51a616e0c7394e26bac831 Mon Sep 17 00:00:00 2001 From: Julien Desfossez Date: Tue, 18 Feb 2014 15:22:08 -0500 Subject: [PATCH] Command to automatically create a local session with all the right parameters Signed-off-by: Julien Desfossez --- src/Makefile.am | 4 +- src/lttng-session.c | 401 ++++++++++++++++++++++++++++++++++++++++++++ src/lttng-session.h | 26 +++ src/lttngtop.c | 6 + 4 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 src/lttng-session.c create mode 100644 src/lttng-session.h diff --git a/src/Makefile.am b/src/Makefile.am index ada47c8..9fe970d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,6 +18,7 @@ noinst_HEADERS = \ lttng-live-comm.h \ lttng-viewer-abi.h \ lttngtop.h \ + lttng-session.h \ $(top_builddir)/lib/babeltrace/format.h \ $(top_builddir)/lib/babeltrace/compat/memstream.h \ $(top_builddir)/lib/babeltrace/compat/string.h \ @@ -61,7 +62,8 @@ lttngtop_SOURCES = \ cursesdisplay.c \ cputop.c \ iostreamtop.c \ - mmap-live.c + mmap-live.c \ + lttng-session.c lttngtop_LDFLAGS = -Wl,--no-as-needed diff --git a/src/lttng-session.c b/src/lttng-session.c new file mode 100644 index 0000000..29676f3 --- /dev/null +++ b/src/lttng-session.c @@ -0,0 +1,401 @@ +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include +#include +#include +#include +#include +#include + +#define event_list "lttng_statedump_start,lttng_statedump_end," \ + "lttng_statedump_process_state,lttng_statedump_file_descriptor," \ + "lttng_statedump_vm_map,lttng_statedump_network_interface," \ + "lttng_statedump_interrupt,sched_process_free," \ + "sched_switch,sched_process_fork" +#define context_list "-t pid -t procname -t tid -t ppid " + +static +int check_or_start_sessiond() +{ + int ret; + int sudo = 0; + + ret = system("pgrep -u root lttng-sessiond >/dev/null"); + if (ret == 0) + goto end; + + if (getuid() != 0) { + fprintf(stderr, "Trying to start lttng-sessiond with sudo\n"); + ret = system("sudo -l lttng-sessiond >/dev/null"); + if (ret < 0) { + fprintf(stderr, "[error] You are not root and not " + "allowed by sudo to start lttng-sessiond\n"); + ret = -1; + goto end; + } + sudo = 1; + } + + if (sudo) + ret = system("sudo lttng-sessiond -d"); + else + ret = system("lttng-sessiond -d"); + + if (ret != 0) { + fprintf(stderr, "Error starting lttng-sessiond as root\n"); + ret = -1; + goto end; + } + +end: + return ret; +} + +static +int check_or_start_relayd() +{ + int ret; + + ret = system("pgrep lttng-relayd >/dev/null"); + if (ret == 0) + goto end; + + ret = system("lttng-relayd -d"); + if (ret != 0) { + fprintf(stderr, "Error starting lttng-relayd\n"); + ret = -1; + goto end; + } + +end: + return ret; +} + +/* + * Return 0 if in tracing group or root, 1 if sudo is needed (and working), + * a negative value on error. + */ +static +int check_tracing_group() +{ + int ret; + + ret = getuid(); + if (ret == 0) + goto end; + + ret = system("groups|grep tracing >/dev/null"); + if (ret == 0) { + goto end; + } + + ret = system("sudo lttng --version >/dev/null"); + if (ret != 0) { + fprintf(stderr, "Error executing lttng with sudo, you need to " + "be root or in the \"tracing\" group to start " + "kernel tracing\n"); + ret = -1; + goto end; + } else { + ret = 1; + } + +end: + return ret; +} + +static +int check_lttng_modules(int sudo) +{ + int ret; + + if (sudo) { + ret = system("sudo lttng list -k | grep sched_switch >/dev/null"); + } else { + ret = system("lttng list -k | grep sched_switch >/dev/null"); + } + if (ret != 0) { + fprintf(stderr, "Error listing kernel events, " + "lttng-modules might not be installed\n"); + goto end; + } + +end: + return ret; +} + +static +int check_requirements(int *sudo) +{ + int ret; + + ret = check_or_start_sessiond(); + if (ret < 0) + goto end; + ret = check_or_start_relayd(); + if (ret < 0) + goto end; + ret = check_tracing_group(); + if (ret < 0) + goto end; + else if (ret == 1) + *sudo = 1; + + ret = check_lttng_modules(*sudo); + if (ret < 0) + goto end; +end: + return ret; +} + +/* + * Allocate a random string, must be freed by the caller. + */ +static +char *random_session_name() +{ + uint64_t id; + char *str = NULL; + int ret; + + FILE *f = fopen( "/dev/urandom", "r"); + if (!f) { + perror("fopen"); + goto end; + } + + ret = fread(&id, 1, sizeof(uint64_t), f); + if (ret < sizeof(id)) { + perror("fread"); + goto end; + } + + ret = asprintf(&str, "lttngtop-%" PRIu64, id); + if (ret < 0) { + fprintf(stderr, "Error allocating session name"); + str = NULL; + goto end; + } + + ret = fclose(f); + if (ret != 0) { + perror("fclose"); + goto end; + } + +end: + return str; +} + +static +int check_session_name(char *name, int sudo) +{ + int ret; + char cmd[1024]; + + ret = sprintf(cmd, "%s lttng list | grep %s >/dev/null", + (sudo) ? "sudo" : " ", name); + if (ret < 0) { + fprintf(stderr, "Allocating cmd\n"); + goto end; + } + + ret = (system(cmd)); + if (ret == 0) { + fprintf(stderr, "Error: session %s already exist, either we " + "are not random enough or something is " + "really wrong\n", name); + ret = -1; + goto end; + } + +end: + return ret; +} + +static +int local_session(char *name, int sudo) +{ + int ret; + char cmd[1024]; + + ret = sprintf(cmd, "%s lttng create %s >/dev/null", + (sudo) ? "sudo" : " ", name); + if (ret < 0) { + fprintf(stderr, "Allocating cmd\n"); + goto end; + } + ret = (system(cmd)); + if (ret != 0) { + fprintf(stderr, "Error: creating the session\n"); + ret = -1; + goto end; + } + +end: + return ret; +} + +static +int enable_event(char *name, int sudo) +{ + int ret; + char cmd[1024]; + + ret = sprintf(cmd, "%s lttng enable-event -s %s -k %s >/dev/null", + (sudo) ? "sudo" : " ", name, event_list); + if (ret < 0) { + fprintf(stderr, "Allocating cmd\n"); + goto end; + } + + ret = (system(cmd)); + if (ret != 0) { + fprintf(stderr, "Error: enabling events\n"); + ret = -1; + goto end; + } + +end: + return ret; +} + +static +int add_contexts(char *name, int sudo) +{ + int ret; + char cmd[1024]; + + ret = sprintf(cmd, "%s lttng add-context -s %s -k %s >/dev/null", + (sudo) ? "sudo" : " ", name, context_list); + if (ret < 0) { + fprintf(stderr, "allocating cmd\n"); + goto end; + } + + ret = (system(cmd)); + if (ret != 0) { + fprintf(stderr, "error: adding contexts\n"); + ret = -1; + goto end; + } + +end: + return ret; +} + +static +int start(char *name, int sudo) +{ + int ret; + char cmd[1024]; + + ret = sprintf(cmd, "%s lttng start %s >/dev/null", + (sudo) ? "sudo" : " ", name); + if (ret < 0) { + fprintf(stderr, "allocating cmd\n"); + goto end; + } + + ret = (system(cmd)); + if (ret != 0) { + fprintf(stderr, "error: starting the session %s\n", name); + ret = -1; + goto end; + } + + ret = sprintf(cmd, "%s lttng list|grep %s|cut -d'(' -f2|cut -d ')' -f1", + (sudo) ? "sudo" : " ", name); + if (ret < 0) { + fprintf(stderr, "allocating cmd\n"); + goto end; + } + fprintf(stderr, "Local session started in "); + ret = (system(cmd)); + if (ret != 0) { + fprintf(stderr, "error: listing the sessions\n"); + ret = -1; + goto end; + } + +end: + return ret; +} + +static +int destroy(char *name, int sudo) +{ + int ret; + char cmd[1024]; + + ret = sprintf(cmd, "%s lttng destroy %s >/dev/null", + (sudo) ? "sudo" : " ", name); + if (ret < 0) { + fprintf(stderr, "allocating cmd\n"); + goto end; + } + + ret = (system(cmd)); + if (ret != 0) { + fprintf(stderr, "error: destroying the session %s\n", name); + ret = -1; + goto end; + } + +end: + return ret; +} + +int create_local_session() +{ + int ret; + char *name; + int sudo = 0; + + ret = check_requirements(&sudo); + + name = random_session_name(); + if (!name) { + ret = -1; + goto end; + } + + ret = check_session_name(name, sudo); + if (ret < 0) { + goto end_free; + } + + ret = local_session(name, sudo); + if (ret < 0) { + goto end_free; + } + + ret = enable_event(name, sudo); + if (ret < 0) { + goto end_free; + } + + ret = add_contexts(name, sudo); + if (ret < 0) { + goto end_free; + } + + ret = start(name, sudo); + if (ret < 0) { + goto end_free; + } + +end_free: + free(name); +end: + return ret; +} + +int destroy_local_session(char *name, int sudo) +{ + return destroy(name, sudo); +} + +/* +int create_live_local_session(); +int destroy_live_local_session(); +*/ diff --git a/src/lttng-session.h b/src/lttng-session.h new file mode 100644 index 0000000..1d85330 --- /dev/null +++ b/src/lttng-session.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2014 Julien Desfossez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LTTNG_SESSION_H +#define LTTNG_SESSION_H + +int create_local_session(); +int destroy_local_session(); +int create_live_local_session(); +int destroy_live_local_session(); + +#endif /* LTTNG_SESSION_H */ diff --git a/src/lttngtop.c b/src/lttngtop.c index cce1901..9cf3a55 100644 --- a/src/lttngtop.c +++ b/src/lttngtop.c @@ -51,6 +51,7 @@ #include "iostreamtop.h" #include "common.h" #include "network-live.h" +#include "lttng-session.h" #ifdef HAVE_LIBNCURSES #include "cursesdisplay.h" @@ -107,6 +108,7 @@ enum { OPT_OUTPUT_FILE, OPT_VERBOSE, OPT_GUI_TEST, + OPT_CREATE_LOCAL_SESSION, }; static struct poptOption long_options[] = { @@ -124,6 +126,7 @@ static struct poptOption long_options[] = { { "output", 'o', POPT_ARG_STRING, &opt_output, OPT_OUTPUT_FILE, NULL, NULL }, { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL }, { "gui-test", 'g', POPT_ARG_NONE, NULL, OPT_GUI_TEST, NULL, NULL }, + { "create-local-session", 0, POPT_ARG_NONE, NULL, OPT_CREATE_LOCAL_SESSION, NULL, NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL }, }; @@ -799,6 +802,9 @@ static int parse_options(int argc, char **argv) exit(EXIT_FAILURE); #endif goto end; + case OPT_CREATE_LOCAL_SESSION: + ret = create_local_session(); + exit(ret); case OPT_TEXTDUMP: opt_textdump = 1; break; -- 2.34.1