X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=ltt-sessiond%2Fmain.c;h=98bdb6a4d6912c8a97117a59c114a6d54ee065ae;hp=7d453214ee1936830fcd846d9411610c414f3082;hb=cf3af59ede4474f4e5123699ee2ee9ee85b7cadd;hpb=0b97ec540cc2e4561ddbef4d4542b6dfb59b0a43 diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 7d453214e..98bdb6a4d 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -99,6 +99,8 @@ static sem_t kconsumerd_sem; static pthread_mutex_t kconsumerd_pid_mutex; /* Mutex to control kconsumerd pid assignation */ +static int modprobe_remove_kernel_modules(void); + /* * Pointer initialized before thread creation. * @@ -144,10 +146,18 @@ static void teardown_kernel_session(struct ltt_session *session) } } +static void stop_threads(void) +{ + /* Stopping all threads */ + DBG("Terminating all threads"); + close(thread_quit_pipe[0]); + close(thread_quit_pipe[1]); +} + /* * Cleanup the daemon */ -static void cleanup() +static void cleanup(void) { int ret; char *cmd; @@ -161,11 +171,6 @@ static void cleanup() 27, 1, 31, 27, 0, 27, 1, 33, 27, 0); /* */ - /* Stopping all threads */ - DBG("Terminating all threads"); - close(thread_quit_pipe[0]); - close(thread_quit_pipe[1]); - DBG("Removing %s directory", LTTNG_RUNDIR); ret = asprintf(&cmd, "rm -rf " LTTNG_RUNDIR); if (ret < 0) { @@ -195,6 +200,9 @@ static void cleanup() DBG("Closing kernel fd"); close(kernel_tracer_fd); + + DBG("Unloading kernel modules"); + modprobe_remove_kernel_modules(); } /* @@ -857,6 +865,23 @@ error: return ret; } +static int join_kconsumerd_thread(void) +{ + void *status; + int ret; + + if (kconsumerd_pid != 0) { + ret = kill(kconsumerd_pid, SIGTERM); + if (ret) { + ERR("Error killing kconsumerd"); + return ret; + } + return pthread_join(kconsumerd_thread, &status); + } else { + return 0; + } +} + /* * Fork and exec a kernel consumer daemon (kconsumerd). * @@ -944,22 +969,67 @@ error: */ static int modprobe_kernel_modules(void) { - int ret = 0, i = 0; + int ret = 0, i; char modprobe[256]; - while (kernel_modules_list[i] != NULL) { - ret = snprintf(modprobe, sizeof(modprobe), "/sbin/modprobe %s", - kernel_modules_list[i]); + for (i = 0; i < ARRAY_SIZE(kernel_modules_list); i++) { + ret = snprintf(modprobe, sizeof(modprobe), + "/sbin/modprobe %s%s", + kernel_modules_list[i].required ? "" : "--quiet ", + kernel_modules_list[i].name); if (ret < 0) { perror("snprintf modprobe"); goto error; } + modprobe[sizeof(modprobe) - 1] = '\0'; ret = system(modprobe); + if (ret == -1) { + ERR("Unable to launch modprobe for module %s", + kernel_modules_list[i].name); + } else if (kernel_modules_list[i].required + && WEXITSTATUS(ret) != 0) { + ERR("Unable to load module %s", + kernel_modules_list[i].name); + } else { + DBG("Modprobe successfully %s", + kernel_modules_list[i].name); + } + } + +error: + return ret; +} + +/* + * modprobe_remove_kernel_modules + * Remove modules in reverse load order. + */ +static int modprobe_remove_kernel_modules(void) +{ + int ret = 0, i; + char modprobe[256]; + + for (i = ARRAY_SIZE(kernel_modules_list) - 1; i >= 0; i--) { + ret = snprintf(modprobe, sizeof(modprobe), + "/sbin/modprobe --remove --quiet %s", + kernel_modules_list[i].name); if (ret < 0) { - ERR("Unable to load module %s", kernel_modules_list[i]); + perror("snprintf modprobe --remove"); + goto error; + } + modprobe[sizeof(modprobe) - 1] = '\0'; + ret = system(modprobe); + if (ret == -1) { + ERR("Unable to launch modprobe --remove for module %s", + kernel_modules_list[i].name); + } else if (kernel_modules_list[i].required + && WEXITSTATUS(ret) != 0) { + ERR("Unable to remove module %s", + kernel_modules_list[i].name); + } else { + DBG("Modprobe removal successful %s", + kernel_modules_list[i].name); } - DBG("Modprobe successfully %s", kernel_modules_list[i]); - i++; } error: @@ -1271,13 +1341,14 @@ static int process_client_msg(struct command_ctx *cmd_ctx) case LTTNG_CREATE_SESSION: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: + case LTTNG_CALIBRATE: break; default: - DBG("Getting session %s by name", cmd_ctx->lsm->session_name); - cmd_ctx->session = find_session_by_name(cmd_ctx->lsm->session_name); + DBG("Getting session %s by name", cmd_ctx->lsm->session.name); + cmd_ctx->session = find_session_by_name(cmd_ctx->lsm->session.name); if (cmd_ctx->session == NULL) { /* If session name not found */ - if (cmd_ctx->lsm->session_name != NULL) { + if (cmd_ctx->lsm->session.name != NULL) { ret = LTTCOMM_SESS_NOT_FOUND; } else { /* If no session name specified */ ret = LTTCOMM_SELECT_SESS; @@ -1291,17 +1362,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } /* - * Check kernel command for kernel session. + * Check domain type for specific "pre-action". */ - switch (cmd_ctx->lsm->cmd_type) { - case LTTNG_ADD_CONTEXT: - case LTTNG_KERNEL_DISABLE_ALL_EVENT: - case LTTNG_DISABLE_CHANNEL: - case LTTNG_KERNEL_DISABLE_EVENT: - case LTTNG_KERNEL_ENABLE_ALL_EVENT: - case LTTNG_KERNEL_ENABLE_CHANNEL: - case LTTNG_KERNEL_ENABLE_EVENT: - case LTTNG_LIST_TRACEPOINTS: + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: /* Kernel tracer check */ if (kernel_tracer_fd == 0) { init_kernel_tracer(); @@ -1312,36 +1376,33 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } /* Need a session for kernel command */ - if (cmd_ctx->lsm->cmd_type != LTTNG_LIST_TRACEPOINTS && - cmd_ctx->session->kernel_session == NULL) { - - ret = create_kernel_session(cmd_ctx->session); - if (ret < 0) { - ret = LTTCOMM_KERN_SESS_FAIL; - goto error; - } - - /* Start the kernel consumer daemon */ - if (kconsumerd_pid == 0) { - ret = start_kconsumerd(); + switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_CREATE_SESSION: + case LTTNG_LIST_SESSIONS: + case LTTNG_LIST_TRACEPOINTS: + case LTTNG_CALIBRATE: + break; + default: + if (cmd_ctx->session->kernel_session == NULL) { + ret = create_kernel_session(cmd_ctx->session); if (ret < 0) { + ret = LTTCOMM_KERN_SESS_FAIL; goto error; } - } - } - } -#ifdef DISABLED - /* Connect to ust apps if available pid */ - if (cmd_ctx->lsm->pid > 0) { - /* Connect to app using ustctl API */ - cmd_ctx->ust_sock = ust_connect_app(cmd_ctx->lsm->pid); - if (cmd_ctx->ust_sock < 0) { - ret = LTTCOMM_NO_TRACEABLE; - goto error; + /* Start the kernel consumer daemon */ + if (kconsumerd_pid == 0) { + ret = start_kconsumerd(); + if (ret < 0) { + goto error; + } + } + } } + break; + default: + break; } -#endif /* DISABLED */ /* Process by command type */ switch (cmd_ctx->lsm->cmd_type) { @@ -1419,10 +1480,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = LTTCOMM_OK; break; } - case LTTNG_KERNEL_DISABLE_EVENT: + case LTTNG_DISABLE_EVENT: { - struct ltt_kernel_channel *chan; - struct ltt_kernel_event *ev; + struct ltt_kernel_channel *kchan; + struct ltt_kernel_event *kevent; /* Setup lttng message with no payload */ ret = setup_lttng_msg(cmd_ctx, 0); @@ -1430,32 +1491,41 @@ static int process_client_msg(struct command_ctx *cmd_ctx) goto setup_error; } - chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, - cmd_ctx->session->kernel_session); - if (chan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } - - ev = get_kernel_event_by_name(cmd_ctx->lsm->u.disable.name, chan); - if (ev != NULL) { - DBG("Disabling kernel event %s for channel %s.", - cmd_ctx->lsm->u.disable.name, cmd_ctx->lsm->u.disable.channel_name); - ret = kernel_disable_event(ev); - if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + kchan = get_kernel_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, + cmd_ctx->session->kernel_session); + if (kchan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; goto error; } + + kevent = get_kernel_event_by_name(cmd_ctx->lsm->u.disable.name, kchan); + if (kevent != NULL) { + DBG("Disabling kernel event %s for channel %s.", kevent->event->name, + kchan->channel->name); + ret = kernel_disable_event(kevent); + if (ret < 0) { + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; + } + } + + kernel_wait_quiescent(kernel_tracer_fd); + break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - kernel_wait_quiescent(kernel_tracer_fd); ret = LTTCOMM_OK; break; } - case LTTNG_KERNEL_DISABLE_ALL_EVENT: + case LTTNG_DISABLE_ALL_EVENT: { - struct ltt_kernel_channel *chan; - struct ltt_kernel_event *ev; + struct ltt_kernel_channel *kchan; + struct ltt_kernel_event *kevent; /* Setup lttng message with no payload */ ret = setup_lttng_msg(cmd_ctx, 0); @@ -1463,33 +1533,41 @@ static int process_client_msg(struct command_ctx *cmd_ctx) goto setup_error; } - DBG("Disabling all enabled kernel events"); - - chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, - cmd_ctx->session->kernel_session); - if (chan == NULL) { - ret = LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; - } + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + DBG("Disabling all enabled kernel events"); + kchan = get_kernel_channel_by_name(cmd_ctx->lsm->u.disable.channel_name, + cmd_ctx->session->kernel_session); + if (kchan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } - /* For each event in the kernel session */ - cds_list_for_each_entry(ev, &chan->events_list.head, list) { - DBG("Disabling kernel event %s for channel %s.", - ev->event->name, cmd_ctx->lsm->u.disable.channel_name); - ret = kernel_disable_event(ev); - if (ret < 0) { - continue; + /* For each event in the kernel session */ + cds_list_for_each_entry(kevent, &kchan->events_list.head, list) { + DBG("Disabling kernel event %s for channel %s.", + kevent->event->name, kchan->channel->name); + ret = kernel_disable_event(kevent); + if (ret < 0) { + continue; + } } + + /* Quiescent wait after event disable */ + kernel_wait_quiescent(kernel_tracer_fd); + break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - /* Quiescent wait after event disable */ - kernel_wait_quiescent(kernel_tracer_fd); ret = LTTCOMM_OK; break; } - case LTTNG_KERNEL_ENABLE_CHANNEL: + case LTTNG_ENABLE_CHANNEL: { - struct ltt_kernel_channel *chan; + struct ltt_kernel_channel *kchan; /* Setup lttng message with no payload */ ret = setup_lttng_msg(cmd_ctx, 0); @@ -1497,44 +1575,53 @@ static int process_client_msg(struct command_ctx *cmd_ctx) goto setup_error; } - chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.enable.channel_name, - cmd_ctx->session->kernel_session); - if (chan == NULL) { - /* Channel not found, creating it */ - DBG("Creating kernel channel"); + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + kchan = get_kernel_channel_by_name(cmd_ctx->lsm->u.enable.channel_name, + cmd_ctx->session->kernel_session); + if (kchan == NULL) { + /* Channel not found, creating it */ + DBG("Creating kernel channel"); - ret = kernel_create_channel(cmd_ctx->session->kernel_session, - &cmd_ctx->lsm->u.channel.chan, cmd_ctx->session->path); - if (ret < 0) { - ret = LTTCOMM_KERN_CHAN_FAIL; - goto error; - } + ret = kernel_create_channel(cmd_ctx->session->kernel_session, + &cmd_ctx->lsm->u.channel.chan, cmd_ctx->session->path); + if (ret < 0) { + ret = LTTCOMM_KERN_CHAN_FAIL; + goto error; + } - /* Notify kernel thread that there is a new channel */ - ret = notify_kernel_pollfd(); - if (ret < 0) { - ret = LTTCOMM_FATAL; - goto error; - } - } else if (chan->enabled == 0) { - ret = kernel_enable_channel(chan); - if (ret < 0) { - if (ret != EEXIST) { - ret = LTTCOMM_KERN_CHAN_ENABLE_FAIL; + /* Notify kernel thread that there is a new channel */ + ret = notify_kernel_pollfd(); + if (ret < 0) { + ret = LTTCOMM_FATAL; + goto error; + } + } else if (kchan->enabled == 0) { + ret = kernel_enable_channel(kchan); + if (ret < 0) { + if (ret != EEXIST) { + ret = LTTCOMM_KERN_CHAN_ENABLE_FAIL; + } + goto error; } - goto error; } + + kernel_wait_quiescent(kernel_tracer_fd); + break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; } - kernel_wait_quiescent(kernel_tracer_fd); ret = LTTCOMM_OK; break; } - case LTTNG_KERNEL_ENABLE_EVENT: + case LTTNG_ENABLE_EVENT: { char *channel_name; struct ltt_kernel_channel *kchan; - struct ltt_kernel_event *ev; + struct ltt_kernel_event *kevent; struct lttng_channel *chan; /* Setup lttng message with no payload */ @@ -1545,57 +1632,65 @@ static int process_client_msg(struct command_ctx *cmd_ctx) channel_name = cmd_ctx->lsm->u.enable.channel_name; - do { - kchan = get_kernel_channel_by_name(channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - DBG("Channel not found. Creating channel %s", channel_name); + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + do { + kchan = get_kernel_channel_by_name(channel_name, + cmd_ctx->session->kernel_session); + if (kchan == NULL) { + DBG("Channel not found. Creating channel %s", channel_name); + + chan = init_default_channel(channel_name); + if (chan == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } - chan = init_default_channel(channel_name); - if (chan == NULL) { - ret = LTTCOMM_FATAL; - goto error; + ret = kernel_create_channel(cmd_ctx->session->kernel_session, + chan, cmd_ctx->session->path); + if (ret < 0) { + ret = LTTCOMM_KERN_CHAN_FAIL; + goto error; + } } + } while (kchan == NULL); - ret = kernel_create_channel(cmd_ctx->session->kernel_session, - chan, cmd_ctx->session->path); - if (ret < 0) { - ret = LTTCOMM_KERN_CHAN_FAIL; + kevent = get_kernel_event_by_name(cmd_ctx->lsm->u.enable.event.name, kchan); + if (kevent == NULL) { + DBG("Creating kernel event %s for channel %s.", + cmd_ctx->lsm->u.enable.event.name, channel_name); + ret = kernel_create_event(&cmd_ctx->lsm->u.enable.event, kchan); + } else { + DBG("Enabling kernel event %s for channel %s.", + kevent->event->name, channel_name); + ret = kernel_enable_event(kevent); + if (ret == -EEXIST) { + ret = LTTCOMM_KERN_EVENT_EXIST; goto error; } } - } while (kchan == NULL); - ev = get_kernel_event_by_name(cmd_ctx->lsm->u.enable.event.name, kchan); - if (ev == NULL) { - DBG("Creating kernel event %s for channel %s.", - cmd_ctx->lsm->u.enable.event.name, channel_name); - ret = kernel_create_event(&cmd_ctx->lsm->u.enable.event, kchan); - } else { - DBG("Enabling kernel event %s for channel %s.", - cmd_ctx->lsm->u.enable.event.name, channel_name); - ret = kernel_enable_event(ev); - if (ret == -EEXIST) { - ret = LTTCOMM_KERN_EVENT_EXIST; + if (ret < 0) { + ret = LTTCOMM_KERN_ENABLE_FAIL; goto error; } - } - if (ret < 0) { - ret = LTTCOMM_KERN_ENABLE_FAIL; + kernel_wait_quiescent(kernel_tracer_fd); + break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; goto error; } - - kernel_wait_quiescent(kernel_tracer_fd); ret = LTTCOMM_OK; break; } - case LTTNG_KERNEL_ENABLE_ALL_EVENT: + case LTTNG_ENABLE_ALL_EVENT: { int size, i; char *channel_name; struct ltt_kernel_channel *kchan; - struct ltt_kernel_event *ev; + struct ltt_kernel_event *kevent; struct lttng_event *event_list; struct lttng_channel *chan; @@ -1609,60 +1704,69 @@ static int process_client_msg(struct command_ctx *cmd_ctx) channel_name = cmd_ctx->lsm->u.enable.channel_name; - do { - kchan = get_kernel_channel_by_name(channel_name, - cmd_ctx->session->kernel_session); - if (kchan == NULL) { - DBG("Channel not found. Creating channel %s", channel_name); + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + do { + kchan = get_kernel_channel_by_name(channel_name, + cmd_ctx->session->kernel_session); + if (kchan == NULL) { + DBG("Channel not found. Creating channel %s", channel_name); + + chan = init_default_channel(channel_name); + if (chan == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } - chan = init_default_channel(channel_name); - if (chan == NULL) { - ret = LTTCOMM_FATAL; - goto error; + ret = kernel_create_channel(cmd_ctx->session->kernel_session, + chan, cmd_ctx->session->path); + if (ret < 0) { + ret = LTTCOMM_KERN_CHAN_FAIL; + goto error; + } } + } while (kchan == NULL); - ret = kernel_create_channel(cmd_ctx->session->kernel_session, - chan, cmd_ctx->session->path); + /* For each event in the kernel session */ + cds_list_for_each_entry(kevent, &kchan->events_list.head, list) { + DBG("Enabling kernel event %s for channel %s.", + kevent->event->name, channel_name); + ret = kernel_enable_event(kevent); if (ret < 0) { - ret = LTTCOMM_KERN_CHAN_FAIL; - goto error; + continue; } } - } while (kchan == NULL); - /* For each event in the kernel session */ - cds_list_for_each_entry(ev, &kchan->events_list.head, list) { - DBG("Enabling kernel event %s for channel %s.", - ev->event->name, channel_name); - ret = kernel_enable_event(ev); - if (ret < 0) { - continue; + size = kernel_list_events(kernel_tracer_fd, &event_list); + if (size < 0) { + ret = LTTCOMM_KERN_LIST_FAIL; + goto error; } - } - - size = kernel_list_events(kernel_tracer_fd, &event_list); - if (size < 0) { - ret = LTTCOMM_KERN_LIST_FAIL; - goto error; - } - for (i = 0; i < size; i++) { - ev = get_kernel_event_by_name(event_list[i].name, kchan); - if (ev == NULL) { - /* Default event type for enable all */ - event_list[i].type = LTTNG_EVENT_TRACEPOINT; - /* Enable each single tracepoint event */ - ret = kernel_create_event(&event_list[i], kchan); - if (ret < 0) { - /* Ignore error here and continue */ + for (i = 0; i < size; i++) { + kevent = get_kernel_event_by_name(event_list[i].name, kchan); + if (kevent == NULL) { + /* Default event type for enable all */ + event_list[i].type = LTTNG_EVENT_TRACEPOINT; + /* Enable each single tracepoint event */ + ret = kernel_create_event(&event_list[i], kchan); + if (ret < 0) { + /* Ignore error here and continue */ + } } } - } - free(event_list); + free(event_list); + + /* Quiescent wait after event enable */ + kernel_wait_quiescent(kernel_tracer_fd); + break; + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; + } - /* Quiescent wait after event enable */ - kernel_wait_quiescent(kernel_tracer_fd); ret = LTTCOMM_OK; break; } @@ -1740,7 +1844,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } /* For each channel */ - cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) { + cds_list_for_each_entry(chan, + &cmd_ctx->session->kernel_session->channel_list.head, list) { if (chan->stream_count == 0) { ret = kernel_open_channel_stream(chan); if (ret < 0) { @@ -1825,7 +1930,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) goto setup_error; } - ret = create_session(cmd_ctx->lsm->session_name, cmd_ctx->lsm->path); + ret = create_session(cmd_ctx->lsm->session.name, cmd_ctx->lsm->session.path); if (ret < 0) { if (ret == -EEXIST) { ret = LTTCOMM_EXIST_SESS; @@ -1849,7 +1954,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Clean kernel session teardown */ teardown_kernel_session(cmd_ctx->session); - ret = destroy_session(cmd_ctx->lsm->session_name); + ret = destroy_session(cmd_ctx->lsm->session.name); if (ret < 0) { ret = LTTCOMM_FATAL; goto error; @@ -1868,47 +1973,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = LTTCOMM_OK; break; } - /* - case UST_CREATE_TRACE: - { - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - ret = ust_create_trace(cmd_ctx); - if (ret < 0) { - goto error; - } - break; - } - case UST_START_TRACE: - { - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - ret = ust_start_trace(cmd_ctx); - if (ret < 0) { - goto setup_error; - } - break; - } - case UST_STOP_TRACE: - { - ret = setup_lttng_msg(cmd_ctx, 0); - if (ret < 0) { - goto setup_error; - } - - ret = ust_stop_trace(cmd_ctx); - if (ret < 0) { - goto setup_error; - } - break; - } - */ case LTTNG_LIST_DOMAINS: { size_t nb_dom = 0; @@ -2012,6 +2076,37 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = LTTCOMM_OK; break; } + + case LTTNG_CALIBRATE: + { + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + switch (cmd_ctx->lsm->domain.type) { + case LTTNG_DOMAIN_KERNEL: + { + struct lttng_kernel_calibrate kcalibrate; + + kcalibrate.type = cmd_ctx->lsm->u.calibrate.type; + ret = kernel_calibrate(kernel_tracer_fd, &kcalibrate); + if (ret < 0) { + ret = LTTCOMM_KERN_ENABLE_FAIL; + goto error; + } + break; + } + default: + /* TODO: Userspace tracing */ + ret = LTTCOMM_NOT_IMPLEMENTED; + goto error; + } + ret = LTTCOMM_OK; + break; + } + default: /* Undefined command */ ret = setup_lttng_msg(cmd_ctx, 0); @@ -2272,7 +2367,7 @@ static int parse_args(int argc, char **argv) * apps_sock - The communication socket for all UST apps. * client_sock - The communication of the cli tool (lttng). */ -static int init_daemon_socket() +static int init_daemon_socket(void) { int ret = 0; mode_t old_umask; @@ -2319,7 +2414,7 @@ end: /* * Check if the global socket is available. If yes, error is returned. */ -static int check_existing_daemon() +static int check_existing_daemon(void) { int ret; @@ -2461,26 +2556,27 @@ error: /* * Signal handler for the daemon + * + * Simply stop all worker threads, leaving main() return gracefully + * after joining all threads and calling cleanup(). */ static void sighandler(int sig) { switch (sig) { - case SIGPIPE: - DBG("SIGPIPE catched"); - return; - case SIGINT: - DBG("SIGINT catched"); - cleanup(); - break; - case SIGTERM: - DBG("SIGTERM catched"); - cleanup(); - break; - default: - break; + case SIGPIPE: + DBG("SIGPIPE catched"); + return; + case SIGINT: + DBG("SIGINT catched"); + stop_threads(); + break; + case SIGTERM: + DBG("SIGTERM catched"); + stop_threads(); + break; + default: + break; } - - exit(EXIT_SUCCESS); } /* @@ -2550,14 +2646,14 @@ int main(int argc, char **argv) const char *home_path; /* Create thread quit pipe */ - if (init_thread_quit_pipe() < 0) { - goto exit; + if ((ret = init_thread_quit_pipe()) < 0) { + goto error; } /* Parse arguments */ progname = argv[0]; if ((ret = parse_args(argc, argv) < 0)) { - goto exit; + goto error; } /* Daemonize */ @@ -2565,7 +2661,7 @@ int main(int argc, char **argv) ret = daemon(0, 0); if (ret < 0) { perror("daemon"); - goto exit; + goto error; } } @@ -2575,7 +2671,7 @@ int main(int argc, char **argv) if (is_root) { ret = create_lttng_rundir(); if (ret < 0) { - goto exit; + goto error; } if (strlen(apps_unix_sock_path) == 0) { @@ -2592,7 +2688,8 @@ int main(int argc, char **argv) if (home_path == NULL) { /* TODO: Add --socket PATH option */ ERR("Can't get HOME directory for sockets creation."); - goto exit; + ret = -EPERM; + goto error; } if (strlen(apps_unix_sock_path) == 0) { @@ -2618,10 +2715,10 @@ int main(int argc, char **argv) if ((ret = check_existing_daemon()) == 0) { ERR("Already running daemon.\n"); /* - * We do not goto error because we must not cleanup() because a daemon - * is already running. + * We do not goto exit because we must not cleanup() + * because a daemon is already running. */ - goto exit; + goto error; } /* After this point, we can safely call cleanup() so goto error is used */ @@ -2635,7 +2732,7 @@ int main(int argc, char **argv) if (is_root) { ret = set_kconsumerd_sockets(); if (ret < 0) { - goto error; + goto exit; } /* Setup kernel tracer */ @@ -2645,18 +2742,18 @@ int main(int argc, char **argv) set_ulimit(); } - if (set_signal_handler() < 0) { - goto error; + if ((ret = set_signal_handler()) < 0) { + goto exit; } /* Setup the needed unix socket */ - if (init_daemon_socket() < 0) { - goto error; + if ((ret = init_daemon_socket()) < 0) { + goto exit; } /* Set credentials to socket */ - if (is_root && (set_permissions() < 0)) { - goto error; + if (is_root && ((ret = set_permissions()) < 0)) { + goto exit; } /* Get parent pid if -S, --sig-parent is specified. */ @@ -2665,8 +2762,8 @@ int main(int argc, char **argv) } /* Setup the kernel pipe for waking up the kernel thread */ - if (create_kernel_poll_pipe() < 0) { - goto error; + if ((ret = create_kernel_poll_pipe()) < 0) { + goto exit; } /* @@ -2675,41 +2772,61 @@ int main(int argc, char **argv) */ session_list_ptr = get_session_list(); - while (1) { - /* Create thread to manage the client socket */ - ret = pthread_create(&client_thread, NULL, thread_manage_clients, (void *) NULL); - if (ret != 0) { - perror("pthread_create"); - goto error; - } + /* Create thread to manage the client socket */ + ret = pthread_create(&client_thread, NULL, thread_manage_clients, (void *) NULL); + if (ret != 0) { + perror("pthread_create"); + goto exit_client; + } - /* Create thread to manage application socket */ - ret = pthread_create(&apps_thread, NULL, thread_manage_apps, (void *) NULL); - if (ret != 0) { - perror("pthread_create"); - goto error; - } + /* Create thread to manage application socket */ + ret = pthread_create(&apps_thread, NULL, thread_manage_apps, (void *) NULL); + if (ret != 0) { + perror("pthread_create"); + goto exit_apps; + } - /* Create kernel thread to manage kernel event */ - ret = pthread_create(&kernel_thread, NULL, thread_manage_kernel, (void *) NULL); - if (ret != 0) { - perror("pthread_create"); - goto error; - } + /* Create kernel thread to manage kernel event */ + ret = pthread_create(&kernel_thread, NULL, thread_manage_kernel, (void *) NULL); + if (ret != 0) { + perror("pthread_create"); + goto exit_kernel; + } - ret = pthread_join(client_thread, &status); - if (ret != 0) { - perror("pthread_join"); - goto error; - } + ret = pthread_join(kernel_thread, &status); + if (ret != 0) { + perror("pthread_join"); + goto error; /* join error, exit without cleanup */ } - cleanup(); - exit(EXIT_SUCCESS); +exit_kernel: + ret = pthread_join(apps_thread, &status); + if (ret != 0) { + perror("pthread_join"); + goto error; /* join error, exit without cleanup */ + } -error: - cleanup(); +exit_apps: + ret = pthread_join(client_thread, &status); + if (ret != 0) { + perror("pthread_join"); + goto error; /* join error, exit without cleanup */ + } + + ret = join_kconsumerd_thread(); + if (ret != 0) { + perror("join_kconsumerd"); + goto error; /* join error, exit without cleanup */ + } +exit_client: exit: + /* + * cleanup() is called when no other thread is running. + */ + cleanup(); + if (!ret) + exit(EXIT_SUCCESS); +error: exit(EXIT_FAILURE); }