From 5b8719f52eb9c8012e3bd48be778548cfbf5a8b8 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Tue, 19 Apr 2011 12:41:02 -0400 Subject: [PATCH] Add support for session daemon auto spawn The lttng tool now spawns a session daemon if no ltt-sessiond is running. Two new options added to control this behavior. Introduce --sessiond-path and --no-sessiond to lttng command line tool. Add --sig-parent to ltt-sessiond that sends a SIGCHLD to the parent pid when the daemon is ready to process client command. Signed-off-by: David Goulet --- include/lttng/liblttngctl.h | 7 ++ ltt-sessiond/ltt-sessiond.c | 23 +++++- lttng/lttng.c | 138 ++++++++++++++++++++++++++++++++++-- lttng/lttng.h | 4 ++ lttng/options.c | 6 ++ 5 files changed, 172 insertions(+), 6 deletions(-) diff --git a/include/lttng/liblttngctl.h b/include/lttng/liblttngctl.h index ed1f703b3..eadc74a60 100644 --- a/include/lttng/liblttngctl.h +++ b/include/lttng/liblttngctl.h @@ -19,8 +19,15 @@ #ifndef _LIBLTTNGCTL_H #define _LIBLTTNGCTL_H +/* Default unix group name for tracing. + */ #define DEFAULT_TRACING_GROUP "tracing" +/* Environment variable to set session daemon + * binary path. + */ +#define LTTNG_SESSIOND_PATH_ENV "LTTNG_SESSIOND_PATH" + /* * From libuuid */ diff --git a/ltt-sessiond/ltt-sessiond.c b/ltt-sessiond/ltt-sessiond.c index d846c89e5..c3b117da3 100644 --- a/ltt-sessiond/ltt-sessiond.c +++ b/ltt-sessiond/ltt-sessiond.c @@ -69,8 +69,10 @@ static struct ltt_session *find_session(uuid_t); /* Variables */ const char *progname; const char *opt_tracing_group; +static int opt_sig_parent; static int opt_daemon; static int is_root; /* Set to 1 if the daemon is running as root */ +static pid_t ppid; static char apps_unix_sock_path[PATH_MAX]; /* Global application Unix socket path */ static char client_unix_sock_path[PATH_MAX]; /* Global client Unix socket path */ @@ -185,6 +187,13 @@ static void *thread_manage_clients(void *data) goto error; } + /* Notify parent pid that we are ready + * to accept command for client side. + */ + if (opt_sig_parent) { + kill(ppid, SIGCHLD); + } + while (1) { /* Blocking call, waiting for transmission */ sock = lttcomm_accept_unix_sock(client_socket); @@ -511,7 +520,8 @@ static void usage(void) "\t-a, --apps-sock PATH\t\tSpecify path for apps unix socket.\n" "\t-d, --daemonize\t\tStart as a daemon.\n" "\t-g, --group NAME\t\tSpecify the tracing group name. (default: tracing)\n" - "\t-V, --version\t\tShow version number.\n", + "\t-V, --version\t\tShow version number.\n" + "\t-S, --sig-parent\t\tSend SIGCHLD to parent pid to notify readiness.\n", progname); } @@ -526,6 +536,7 @@ static int parse_args(int argc, char **argv) { "client-sock", 1, 0, 'c' }, { "apps-sock", 1, 0, 'a' }, { "daemonize", 0, 0, 'd' }, + { "sig-parent", 0, 0, 'S' }, { "help", 0, 0, 'h' }, { "group", 1, 0, 'g' }, { "version", 0, 0, 'V' }, @@ -534,7 +545,7 @@ static int parse_args(int argc, char **argv) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "dhV" "a:c:g:s:", long_options, &option_index); + c = getopt_long(argc, argv, "dhVS" "a:c:g:s:", long_options, &option_index); if (c == -1) { break; } @@ -564,6 +575,9 @@ static int parse_args(int argc, char **argv) case 'V': fprintf(stdout, "%s\n", VERSION); exit(EXIT_SUCCESS); + case 'S': + opt_sig_parent = 1; + break; default: /* Unknown option or other error. * Error is printed by getopt, just return */ @@ -874,6 +888,11 @@ int main(int argc, char **argv) goto error; } + /* Get parent pid if -S, --sig-parent is specified. */ + if (opt_sig_parent) { + ppid = getppid(); + } + while (1) { /* Create thread to manage the client socket */ ret = pthread_create(&threads[0], NULL, thread_manage_clients, (void *) NULL); diff --git a/lttng/lttng.c b/lttng/lttng.c index 625855288..907984370 100644 --- a/lttng/lttng.c +++ b/lttng/lttng.c @@ -41,6 +41,8 @@ static char *progname; /* Prototypes */ static int process_client_opt(void); static int process_opt_list_apps(void); +static void sighandler(int sig); +static int set_signal_handler(void); /* * start_client @@ -113,25 +115,148 @@ error: return ret; } +/* + * spawn_sessiond + * + * Spawn a session daemon by forking and execv. + */ +static int spawn_sessiond(char *pathname) +{ + int ret = 0; + pid_t pid; + + MSG("Spawning session daemon"); + pid = fork(); + if (pid == 0) { + /* Spawn session daemon and tell + * it to signal us when ready. + */ + ret = execlp(pathname, "ltt-sessiond", "--sig-parent", NULL); + if (ret < 0) { + if (errno == ENOENT) { + ERR("No session daemon found. Use --sessiond-path."); + } else { + perror("execlp"); + } + kill(getppid(), SIGTERM); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); + } else if (pid > 0) { + /* Wait for ltt-sessiond to start */ + pause(); + goto end; + } else { + perror("fork"); + ret = -1; + goto end; + } + +end: + return ret; +} + /* * check_ltt_sessiond * * Check if the session daemon is available using - * the liblttngctl API for the check. + * the liblttngctl API for the check. If not, try to + * spawn a daemon. */ static int check_ltt_sessiond(void) { int ret; + char *pathname = NULL; ret = lttng_check_session_daemon(); if (ret < 0) { - ERR("No session daemon found. Aborting."); + /* Try command line option path */ + if (opt_sessiond_path != NULL) { + ret = access(opt_sessiond_path, F_OK | X_OK); + if (ret < 0) { + ERR("No such file: %s", opt_sessiond_path); + goto end; + } + pathname = opt_sessiond_path; + } else { + /* Try LTTNG_SESSIOND_PATH env variable */ + pathname = strdup(getenv(LTTNG_SESSIOND_PATH_ENV)); + } + + /* Let's rock and roll */ + if (pathname == NULL) { + ret = asprintf(&pathname, "ltt-sessiond"); + if (ret < 0) { + goto end; + } + } + + ret = spawn_sessiond(pathname); + free(pathname); + if (ret < 0) { + ERR("Problem occurs when starting %s", pathname); + goto end; + } } +end: return ret; } +/* + * set_signal_handler + * + * Setup signal handler for SIGCHLD and SIGTERM. + */ +static int set_signal_handler(void) +{ + int ret = 0; + struct sigaction sa; + sigset_t sigset; + + if ((ret = sigemptyset(&sigset)) < 0) { + perror("sigemptyset"); + goto end; + } + + sa.sa_handler = sighandler; + sa.sa_mask = sigset; + sa.sa_flags = 0; + if ((ret = sigaction(SIGCHLD, &sa, NULL)) < 0) { + perror("sigaction"); + goto end; + } + if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) { + perror("sigaction"); + goto end; + } + +end: + return ret; +} + +/* + * sighandler + * + * Signal handler for the daemon + */ +static void sighandler(int sig) +{ + DBG("%d received", sig); + switch (sig) { + case SIGTERM: + clean_exit(EXIT_FAILURE); + break; + case SIGCHLD: + /* Notify is done */ + break; + default: + break; + } + + return; +} /* * clean_exit */ @@ -142,7 +267,7 @@ void clean_exit(int code) } /* - * main + * main */ int main(int argc, char *argv[]) { @@ -160,6 +285,11 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } + ret = set_signal_handler(); + if (ret < 0) { + return ret; + } + if (opt_tracing_group != NULL) { DBG("Set tracing group to '%s'", opt_tracing_group); lttng_set_tracing_group(opt_tracing_group); @@ -177,7 +307,7 @@ int main(int argc, char *argv[]) /* Check if the lttng session daemon is running. * If no, a daemon will be spawned. */ - if (check_ltt_sessiond() < 0) { + if (opt_no_sessiond == 0 && (check_ltt_sessiond() < 0)) { return EXIT_FAILURE; } diff --git a/lttng/lttng.h b/lttng/lttng.h index 587ff0e6d..4a4d181d5 100644 --- a/lttng/lttng.h +++ b/lttng/lttng.h @@ -28,6 +28,10 @@ extern int opt_verbose; extern int opt_quiet; extern char *opt_tracing_group; extern char *opt_session_name; +extern char *opt_sessiond_path; extern int opt_list_apps; +extern int opt_no_sessiond; + +#define SESSIOND_PATH_NUM 6 #endif /* _LTTNG_H */ diff --git a/lttng/options.c b/lttng/options.c index 784e4fabc..ee13f120b 100644 --- a/lttng/options.c +++ b/lttng/options.c @@ -24,10 +24,12 @@ /* Option variables */ char *opt_tracing_group; char *opt_session_name; +char *opt_sessiond_path; int opt_trace_kernel = 0; int opt_quiet = 0; int opt_verbose = 0; int opt_list_apps = 0; +int opt_no_sessiond = 0; enum { OPT_HELP = 42, @@ -43,6 +45,8 @@ static struct poptOption long_options[] = { {"quiet", 'q', POPT_ARG_VAL, &opt_quiet, 1, 0}, {"verbose", 'v', POPT_ARG_VAL, &opt_verbose, 1, 0}, {"list-apps", 'l', POPT_ARG_VAL, &opt_list_apps, 1, 0}, + {"no-sessiond", 0, POPT_ARG_VAL, &opt_no_sessiond, 1, 0}, + {"sessiond-path", 0, POPT_ARG_STRING, &opt_sessiond_path, 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -60,6 +64,8 @@ static void usage(FILE *ofp) fprintf(ofp, " -q, --quiet Quiet mode\n"); fprintf(ofp, " --help Show help\n"); fprintf(ofp, " --group NAME Unix tracing group name. (default: tracing)\n"); + fprintf(ofp, " --no-sessiond Don't spawn a session daemon.\n"); + fprintf(ofp, " --sessiond-path Session daemon full path\n"); fprintf(ofp, "\n"); fprintf(ofp, "Tracing options:\n"); //fprintf(ofp, " --session [NAME] Specify tracing session. If no NAME is given\n"); -- 2.34.1