X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=bbbc75588c6f044a159f05a9588579f639037ec4;hp=71291f7c549096d74d3194990a92d1f14ed5f05b;hb=de2fad4824768bbd5d1ed4f630caae1ee1f842fd;hpb=d5b9fd2fecf971e4a57a1ee0ffede64ef4e0ad6f diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 71291f7c5..bbbc75588 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -76,8 +77,12 @@ static int opt_daemon; static int opt_no_kernel; static int is_root; /* Set to 1 if the daemon is running as root */ static pid_t ppid; /* Parent PID for --sig-parent option */ +static pid_t child_ppid; /* Internal parent PID use with daemonize. */ static char *rundir; +/* Set to 1 when a SIGUSR1 signal is received. */ +static int recv_child_signal; + /* * Consumer daemon specific control data. Every value not initialized here is * set to 0 by the static definition. @@ -2931,10 +2936,74 @@ skip_domain: break; } case LTTNG_ENABLE_EVENT: + case LTTNG_ENABLE_EVENT_WITH_EXCLUSION: + case LTTNG_ENABLE_EVENT_WITH_FILTER: { - ret = cmd_enable_event(cmd_ctx->session, &cmd_ctx->lsm->domain, - cmd_ctx->lsm->u.enable.channel_name, - &cmd_ctx->lsm->u.enable.event, NULL, kernel_poll_pipe[1]); + struct lttng_event_exclusion *exclusion = NULL; + struct lttng_filter_bytecode *bytecode = NULL; + + if (cmd_ctx->lsm->cmd_type == LTTNG_ENABLE_EVENT || + (cmd_ctx->lsm->u.enable.exclusion_count == 0 && cmd_ctx->lsm->u.enable.bytecode_len == 0)) { + ret = cmd_enable_event(cmd_ctx->session, &cmd_ctx->lsm->domain, + cmd_ctx->lsm->u.enable.channel_name, + &cmd_ctx->lsm->u.enable.event, NULL, NULL, kernel_poll_pipe[1]); + } else { + if (cmd_ctx->lsm->u.enable.exclusion_count != 0) { + exclusion = zmalloc(sizeof(struct lttng_event_exclusion) + + cmd_ctx->lsm->u.enable.exclusion_count * LTTNG_SYMBOL_NAME_LEN); + if (!exclusion) { + ret = LTTNG_ERR_EXCLUSION_NOMEM; + goto error; + } + DBG("Receiving var len data from client ..."); + exclusion->count = cmd_ctx->lsm->u.enable.exclusion_count; + ret = lttcomm_recv_unix_sock(sock, exclusion->names, + cmd_ctx->lsm->u.enable.exclusion_count * LTTNG_SYMBOL_NAME_LEN); + if (ret <= 0) { + DBG("Nothing recv() from client var len data... continuing"); + *sock_error = 1; + ret = LTTNG_ERR_EXCLUSION_INVAL; + goto error; + } + } + if (cmd_ctx->lsm->u.enable.bytecode_len != 0) { + bytecode = zmalloc(cmd_ctx->lsm->u.enable.bytecode_len); + if (!bytecode) { + if (!exclusion) + free(exclusion); + ret = LTTNG_ERR_FILTER_NOMEM; + goto error; + } + /* Receive var. len. data */ + DBG("Receiving var len data from client ..."); + ret = lttcomm_recv_unix_sock(sock, bytecode, + cmd_ctx->lsm->u.enable.bytecode_len); + if (ret <= 0) { + DBG("Nothing recv() from client car len data... continuing"); + *sock_error = 1; + if (!exclusion) + free(exclusion); + ret = LTTNG_ERR_FILTER_INVAL; + goto error; + } + + if (bytecode->len + sizeof(*bytecode) + != cmd_ctx->lsm->u.enable.bytecode_len) { + free(bytecode); + if (!exclusion) + free(exclusion); + ret = LTTNG_ERR_FILTER_INVAL; + goto error; + } + } + + ret = cmd_enable_event(cmd_ctx->session, + &cmd_ctx->lsm->domain, + cmd_ctx->lsm->u.enable.channel_name, + &cmd_ctx->lsm->u.enable.event, bytecode, + exclusion, + kernel_poll_pipe[1]); + } break; } case LTTNG_ENABLE_ALL_EVENT: @@ -3258,46 +3327,6 @@ skip_domain: cmd_ctx->lsm->u.reg.path, cdata); break; } - case LTTNG_ENABLE_EVENT_WITH_FILTER: - { - struct lttng_filter_bytecode *bytecode; - - if (cmd_ctx->lsm->u.enable.bytecode_len > LTTNG_FILTER_MAX_LEN) { - ret = LTTNG_ERR_FILTER_INVAL; - goto error; - } - if (cmd_ctx->lsm->u.enable.bytecode_len == 0) { - ret = LTTNG_ERR_FILTER_INVAL; - goto error; - } - bytecode = zmalloc(cmd_ctx->lsm->u.enable.bytecode_len); - if (!bytecode) { - ret = LTTNG_ERR_FILTER_NOMEM; - goto error; - } - /* Receive var. len. data */ - DBG("Receiving var len data from client ..."); - ret = lttcomm_recv_unix_sock(sock, bytecode, - cmd_ctx->lsm->u.enable.bytecode_len); - if (ret <= 0) { - DBG("Nothing recv() from client var len data... continuing"); - *sock_error = 1; - ret = LTTNG_ERR_FILTER_INVAL; - goto error; - } - - if (bytecode->len + sizeof(*bytecode) - != cmd_ctx->lsm->u.enable.bytecode_len) { - free(bytecode); - ret = LTTNG_ERR_FILTER_INVAL; - goto error; - } - - ret = cmd_enable_event(cmd_ctx->session, &cmd_ctx->lsm->domain, - cmd_ctx->lsm->u.enable.channel_name, - &cmd_ctx->lsm->u.enable.event, bytecode, kernel_poll_pipe[1]); - break; - } case LTTNG_DATA_PENDING: { ret = cmd_data_pending(cmd_ctx->session); @@ -3696,11 +3725,17 @@ static void *thread_manage_clients(void *data) /* * Notify parent pid that we are ready to accept command for client side. + * This ppid is the one from the external process that spawned us. */ if (opt_sig_parent) { kill(ppid, SIGUSR1); } + /* Notify the parent of the fork() process that we are ready. */ + if (opt_daemon) { + kill(child_ppid, SIGUSR1); + } + if (testpoint(thread_manage_clients_before_loop)) { goto error; } @@ -3921,7 +3956,7 @@ static void usage(void) fprintf(stderr, " -d, --daemonize Start as a daemon.\n"); fprintf(stderr, " -g, --group NAME Specify the tracing group name. (default: tracing)\n"); fprintf(stderr, " -V, --version Show version number.\n"); - fprintf(stderr, " -S, --sig-parent Send SIGCHLD to parent pid to notify readiness.\n"); + fprintf(stderr, " -S, --sig-parent Send SIGUSR1 to parent pid to notify readiness.\n"); fprintf(stderr, " -q, --quiet No output at all.\n"); fprintf(stderr, " -v, --verbose Verbose mode. Activate DBG() macro.\n"); fprintf(stderr, " -p, --pidfile FILE Write a pid to FILE name overriding the default value.\n"); @@ -4342,6 +4377,9 @@ static void sighandler(int sig) DBG("SIGTERM caught"); stop_threads(); break; + case SIGUSR1: + CMM_STORE_SHARED(recv_child_signal, 1); + break; default: break; } @@ -4380,7 +4418,12 @@ static int set_signal_handler(void) return ret; } - DBG("Signal handler set for SIGTERM, SIGPIPE and SIGINT"); + if ((ret = sigaction(SIGUSR1, &sa, NULL)) < 0) { + PERROR("sigaction"); + return ret; + } + + DBG("Signal handler set for SIGTERM, SIGUSR1, SIGPIPE and SIGINT"); return ret; } @@ -4464,6 +4507,95 @@ error: return; } +/* + * Daemonize this process by forking and making the parent wait for the child + * to signal it indicating readiness. Once received, the parent successfully + * quits. + * + * The child process undergoes the same action that daemon(3) does meaning + * setsid, chdir, and dup /dev/null into 0, 1 and 2. + * + * Return 0 on success else -1 on error. + */ +static int daemonize(void) +{ + int ret; + pid_t pid; + + /* Get parent pid of this process. */ + child_ppid = getppid(); + + pid = fork(); + if (pid < 0) { + PERROR("fork"); + goto error; + } else if (pid == 0) { + int fd; + pid_t sid; + + /* Child */ + + /* + * Get the newly created parent pid so we can signal that process when + * we are ready to operate. + */ + child_ppid = getppid(); + + sid = setsid(); + if (sid < 0) { + PERROR("setsid"); + goto error; + } + + /* Try to change directory to /. If we can't well at least notify. */ + ret = chdir("/"); + if (ret < 0) { + PERROR("chdir"); + } + + fd = open(_PATH_DEVNULL, O_RDWR, 0); + if (fd < 0) { + PERROR("open %s", _PATH_DEVNULL); + /* Let 0, 1 and 2 open since we can't bind them to /dev/null. */ + } else { + (void) dup2(fd, STDIN_FILENO); + (void) dup2(fd, STDOUT_FILENO); + (void) dup2(fd, STDERR_FILENO); + if (fd > 2) { + ret = close(fd); + if (ret < 0) { + PERROR("close"); + } + } + } + goto end; + } else { + /* Parent */ + + /* + * Waiting for child to notify this parent that it can exit. Note that + * sleep() is interrupted before the 1 second delay as soon as the + * signal is received, so it will not cause visible delay for the + * user. + */ + while (!CMM_LOAD_SHARED(recv_child_signal)) { + sleep(1); + } + + /* + * From this point on, the parent can exit and the child is now an + * operationnal session daemon ready to serve clients and applications. + */ + exit(EXIT_SUCCESS); + } + +end: + return 0; + +error: + return -1; +} + /* * main */ @@ -4477,6 +4609,10 @@ int main(int argc, char **argv) rcu_register_thread(); + if ((ret = set_signal_handler()) < 0) { + goto error; + } + setup_consumerd_path(); page_size = sysconf(_SC_PAGESIZE); @@ -4496,20 +4632,15 @@ int main(int argc, char **argv) if (opt_daemon) { int i; - /* - * fork - * child: setsid, close FD 0, 1, 2, chdir / - * parent: exit (if fork is successful) - */ - ret = daemon(0, 0); + ret = daemonize(); if (ret < 0) { - PERROR("daemon"); goto error; } + /* - * We are in the child. Make sure all other file - * descriptors are closed, in case we are called with - * more opened file descriptors than the standard ones. + * We are in the child. Make sure all other file descriptors are + * closed, in case we are called with more opened file descriptors than + * the standard ones. */ for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) { (void) close(i); @@ -4702,10 +4833,6 @@ int main(int argc, char **argv) goto exit; } - if ((ret = set_signal_handler()) < 0) { - goto exit; - } - /* Setup the needed unix socket */ if ((ret = init_daemon_socket()) < 0) { goto exit;