X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=12322837e7f681038e0ed6fe54d2ac72e035668d;hp=886456a0ce8ce56f37867fd2a7b04871f5e813fa;hb=ca2eb7f43cf00d12f563905d741a6789c3d130ee;hpb=e0c7ec2b3d96dd7ddd9375c5f72239a733d0cf24 diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 886456a0c..12322837e 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -17,7 +17,6 @@ */ #define _GNU_SOURCE -#include #include #include #include @@ -40,6 +39,7 @@ #include #include +#include #include #include #include @@ -77,7 +77,7 @@ struct consumer_data { /* Const values */ const char default_home_dir[] = DEFAULT_HOME_DIR; -const char default_tracing_group[] = LTTNG_DEFAULT_TRACING_GROUP; +const char default_tracing_group[] = DEFAULT_TRACING_GROUP; const char default_ust_sock_dir[] = DEFAULT_UST_SOCK_DIR; const char default_global_apps_pipe[] = DEFAULT_GLOBAL_APPS_PIPE; @@ -100,16 +100,22 @@ static struct consumer_data kconsumer_data = { .type = LTTNG_CONSUMER_KERNEL, .err_unix_sock_path = DEFAULT_KCONSUMERD_ERR_SOCK_PATH, .cmd_unix_sock_path = DEFAULT_KCONSUMERD_CMD_SOCK_PATH, + .err_sock = -1, + .cmd_sock = -1, }; static struct consumer_data ustconsumer64_data = { .type = LTTNG_CONSUMER64_UST, .err_unix_sock_path = DEFAULT_USTCONSUMERD64_ERR_SOCK_PATH, .cmd_unix_sock_path = DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH, + .err_sock = -1, + .cmd_sock = -1, }; static struct consumer_data ustconsumer32_data = { .type = LTTNG_CONSUMER32_UST, .err_unix_sock_path = DEFAULT_USTCONSUMERD32_ERR_SOCK_PATH, .cmd_unix_sock_path = DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH, + .err_sock = -1, + .cmd_sock = -1, }; static int dispatch_thread_exit; @@ -122,22 +128,22 @@ static char client_unix_sock_path[PATH_MAX]; static char wait_shm_path[PATH_MAX]; /* Sockets and FDs */ -static int client_sock; -static int apps_sock; -static int kernel_tracer_fd; -static int kernel_poll_pipe[2]; +static int client_sock = -1; +static int apps_sock = -1; +static int kernel_tracer_fd = -1; +static int kernel_poll_pipe[2] = { -1, -1 }; /* * Quit pipe for all threads. This permits a single cancellation point * for all threads when receiving an event on the pipe. */ -static int thread_quit_pipe[2]; +static int thread_quit_pipe[2] = { -1, -1 }; /* * This pipe is used to inform the thread managing application communication * that a command is queued and ready to be processed. */ -static int apps_cmd_pipe[2]; +static int apps_cmd_pipe[2] = { -1, -1 }; /* Pthread, Mutexes and Semaphores */ static pthread_t apps_thread; @@ -215,11 +221,11 @@ void setup_consumerd_path(void) if (bin) { consumerd64_bin = bin; } - libdir = getenv("LTTNG_TOOLS_CONSUMERD32_LIBDIR"); + libdir = getenv("LTTNG_CONSUMERD32_LIBDIR"); if (libdir) { consumerd32_libdir = libdir; } - libdir = getenv("LTTNG_TOOLS_CONSUMERD64_LIBDIR"); + libdir = getenv("LTTNG_CONSUMERD64_LIBDIR"); if (libdir) { consumerd64_libdir = libdir; } @@ -295,14 +301,22 @@ static gid_t allowed_group(void) */ static int init_thread_quit_pipe(void) { - int ret; + int ret, i; - ret = pipe2(thread_quit_pipe, O_CLOEXEC); + ret = pipe(thread_quit_pipe); if (ret < 0) { - perror("thread quit pipe"); + PERROR("thread quit pipe"); goto error; } + for (i = 0; i < 2; i++) { + ret = fcntl(thread_quit_pipe[i], F_SETFD, FD_CLOEXEC); + if (ret < 0) { + PERROR("fcntl"); + goto error; + } + } + error: return ret; } @@ -314,7 +328,7 @@ error: static void teardown_kernel_session(struct ltt_session *session) { if (!session->kernel_session) { - DBG3("No kernel session when tearingdown session"); + DBG3("No kernel session when tearing down session"); return; } @@ -324,7 +338,8 @@ static void teardown_kernel_session(struct ltt_session *session) * If a custom kernel consumer was registered, close the socket before * tearing down the complete kernel session structure */ - if (session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) { + if (kconsumer_data.cmd_sock >= 0 && + session->kernel_session->consumer_fd != kconsumer_data.cmd_sock) { lttcomm_close_unix_sock(session->kernel_session->consumer_fd); } @@ -340,7 +355,7 @@ static void teardown_ust_session(struct ltt_session *session) int ret; if (!session->ust_session) { - DBG3("No UST session when tearingdown session"); + DBG3("No UST session when tearing down session"); return; } @@ -378,7 +393,7 @@ static void stop_threads(void) */ static void cleanup(void) { - int ret; + int ret, i; char *cmd; struct ltt_session *sess, *stmp; @@ -397,7 +412,7 @@ static void cleanup(void) } free(cmd); - DBG("Cleaning up all session"); + DBG("Cleaning up all sessions"); /* Destroy session list mutex */ if (session_list_ptr != NULL) { @@ -419,13 +434,44 @@ static void cleanup(void) if (is_root && !opt_no_kernel) { DBG2("Closing kernel fd"); - close(kernel_tracer_fd); + if (kernel_tracer_fd >= 0) { + ret = close(kernel_tracer_fd); + if (ret) { + PERROR("close"); + } + } DBG("Unloading kernel modules"); modprobe_remove_lttng_all(); } - close(thread_quit_pipe[0]); - close(thread_quit_pipe[1]); + /* + * Closing all pipes used for communication between threads. + */ + for (i = 0; i < 2; i++) { + if (kernel_poll_pipe[i] >= 0) { + ret = close(kernel_poll_pipe[i]); + if (ret) { + PERROR("close"); + } + + } + } + for (i = 0; i < 2; i++) { + if (thread_quit_pipe[i] >= 0) { + ret = close(thread_quit_pipe[i]); + if (ret) { + PERROR("close"); + } + } + } + for (i = 0; i < 2; i++) { + if (apps_cmd_pipe[i] >= 0) { + ret = close(apps_cmd_pipe[i]); + if (ret) { + PERROR("close"); + } + } + } /* */ DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm" @@ -489,7 +535,7 @@ static int send_kconsumer_channel_streams(struct consumer_data *consumer_data, DBG("Sending channel %d to consumer", lkm.u.channel.channel_key); ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm)); if (ret < 0) { - perror("send consumer channel"); + PERROR("send consumer channel"); goto error; } @@ -511,12 +557,12 @@ static int send_kconsumer_channel_streams(struct consumer_data *consumer_data, DBG("Sending stream %d to consumer", lkm.u.stream.stream_key); ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm)); if (ret < 0) { - perror("send consumer stream"); + PERROR("send consumer stream"); goto error; } ret = lttcomm_send_fds_unix_sock(sock, &stream->fd, 1); if (ret < 0) { - perror("send consumer stream ancillary data"); + PERROR("send consumer stream ancillary data"); goto error; } } @@ -542,12 +588,12 @@ static int send_kconsumer_session_streams(struct consumer_data *consumer_data, DBG("Sending metadata stream fd"); - /* Extra protection. It's NOT supposed to be set to 0 at this point */ - if (session->consumer_fd == 0) { + /* Extra protection. It's NOT supposed to be set to -1 at this point */ + if (session->consumer_fd < 0) { session->consumer_fd = consumer_data->cmd_sock; } - if (session->metadata_stream_fd != 0) { + if (session->metadata_stream_fd >= 0) { /* Send metadata channel fd */ lkm.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL; lkm.u.channel.channel_key = session->metadata->fd; @@ -556,7 +602,7 @@ static int send_kconsumer_session_streams(struct consumer_data *consumer_data, DBG("Sending metadata channel %d to consumer", lkm.u.stream.stream_key); ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm)); if (ret < 0) { - perror("send consumer channel"); + PERROR("send consumer channel"); goto error; } @@ -574,12 +620,12 @@ static int send_kconsumer_session_streams(struct consumer_data *consumer_data, DBG("Sending metadata stream %d to consumer", lkm.u.stream.stream_key); ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm)); if (ret < 0) { - perror("send consumer stream"); + PERROR("send consumer stream"); goto error; } ret = lttcomm_send_fds_unix_sock(sock, &session->metadata_stream_fd, 1); if (ret < 0) { - perror("send consumer stream"); + PERROR("send consumer stream"); goto error; } } @@ -640,7 +686,7 @@ static int setup_lttng_msg(struct command_ctx *cmd_ctx, size_t size) cmd_ctx->llm = zmalloc(sizeof(struct lttcomm_lttng_msg) + buf_size); if (cmd_ctx->llm == NULL) { - perror("zmalloc"); + PERROR("zmalloc"); ret = -ENOMEM; goto error; } @@ -721,8 +767,8 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd) continue; } - /* This is not suppose to be 0 but this is an extra security check */ - if (session->kernel_session->consumer_fd == 0) { + /* This is not suppose to be -1 but this is an extra security check */ + if (session->kernel_session->consumer_fd < 0) { session->kernel_session->consumer_fd = consumer_data->cmd_sock; } @@ -769,12 +815,18 @@ static void update_ust_app(int app_sock) { struct ltt_session *sess, *stmp; + session_lock_list(); + /* For all tracing session(s) */ cds_list_for_each_entry_safe(sess, stmp, &session_list_ptr->head, list) { + session_lock(sess); if (sess->ust_session) { ust_app_global_update(sess->ust_session, app_sock); } + session_unlock(sess); } + + session_unlock_list(); } /* @@ -794,7 +846,7 @@ static void *thread_manage_kernel(void *data) ret = create_thread_poll_set(&events, 2); if (ret < 0) { - goto error; + goto error_poll_create; } ret = lttng_poll_add(&events, kernel_poll_pipe[0], LPOLLIN); @@ -825,8 +877,15 @@ static void *thread_manage_kernel(void *data) lttng_poll_reset(&events); /* Poll infinite value of time */ + restart: ret = lttng_poll_wait(&events, -1); if (ret < 0) { + /* + * Restart interrupted system call. + */ + if (errno == EINTR) { + goto restart; + } goto error; } else if (ret == 0) { /* Should not happen since timeout is infinite */ @@ -872,12 +931,9 @@ static void *thread_manage_kernel(void *data) } error: - DBG("Kernel thread dying"); - close(kernel_poll_pipe[0]); - close(kernel_poll_pipe[1]); - lttng_poll_clean(&events); - +error_poll_create: + DBG("Kernel thread dying"); return NULL; } @@ -886,7 +942,7 @@ error: */ static void *thread_manage_consumer(void *data) { - int sock = 0, i, ret, pollfd; + int sock = -1, i, ret, pollfd; uint32_t revents, nb_fd; enum lttcomm_return_code code; struct lttng_poll_event events; @@ -896,7 +952,7 @@ static void *thread_manage_consumer(void *data) ret = lttcomm_listen_unix_sock(consumer_data->err_sock); if (ret < 0) { - goto error; + goto error_listen; } /* @@ -905,7 +961,7 @@ static void *thread_manage_consumer(void *data) */ ret = create_thread_poll_set(&events, 2); if (ret < 0) { - goto error; + goto error_poll; } ret = lttng_poll_add(&events, consumer_data->err_sock, LPOLLIN | LPOLLRDHUP); @@ -916,8 +972,15 @@ static void *thread_manage_consumer(void *data) nb_fd = LTTNG_POLL_GETNB(&events); /* Inifinite blocking call, waiting for transmission */ +restart: ret = lttng_poll_wait(&events, -1); if (ret < 0) { + /* + * Restart interrupted system call. + */ + if (errno == EINTR) { + goto restart; + } goto error; } @@ -987,8 +1050,15 @@ static void *thread_manage_consumer(void *data) nb_fd = LTTNG_POLL_GETNB(&events); /* Inifinite blocking call, waiting for transmission */ +restart_poll: ret = lttng_poll_wait(&events, -1); if (ret < 0) { + /* + * Restart interrupted system call. + */ + if (errno == EINTR) { + goto restart_poll; + } goto error; } @@ -1023,16 +1093,33 @@ static void *thread_manage_consumer(void *data) ERR("consumer return code : %s", lttcomm_get_readable_code(-code)); error: - DBG("consumer thread dying"); - close(consumer_data->err_sock); - close(consumer_data->cmd_sock); - close(sock); + if (consumer_data->err_sock >= 0) { + ret = close(consumer_data->err_sock); + if (ret) { + PERROR("close"); + } + } + if (consumer_data->cmd_sock >= 0) { + ret = close(consumer_data->cmd_sock); + if (ret) { + PERROR("close"); + } + } + if (sock >= 0) { + ret = close(sock); + if (ret) { + PERROR("close"); + } + } unlink(consumer_data->err_unix_sock_path); unlink(consumer_data->cmd_unix_sock_path); consumer_data->pid = 0; lttng_poll_clean(&events); +error_poll: +error_listen: + DBG("consumer thread cleanup completed"); return NULL; } @@ -1054,7 +1141,7 @@ static void *thread_manage_apps(void *data) ret = create_thread_poll_set(&events, 2); if (ret < 0) { - goto error; + goto error_poll_create; } ret = lttng_poll_add(&events, apps_cmd_pipe[0], LPOLLIN | LPOLLRDHUP); @@ -1071,8 +1158,15 @@ static void *thread_manage_apps(void *data) DBG("Apps thread polling on %d fds", nb_fd); /* Inifinite blocking call, waiting for transmission */ + restart: ret = lttng_poll_wait(&events, -1); if (ret < 0) { + /* + * Restart interrupted system call. + */ + if (errno == EINTR) { + goto restart; + } goto error; } @@ -1096,7 +1190,7 @@ static void *thread_manage_apps(void *data) /* Empty pipe */ ret = read(apps_cmd_pipe[0], &ust_cmd, sizeof(ust_cmd)); if (ret < 0 || ret < sizeof(ust_cmd)) { - perror("read apps cmd pipe"); + PERROR("read apps cmd pipe"); goto error; } @@ -1132,8 +1226,10 @@ static void *thread_manage_apps(void *data) /* * We just need here to monitor the close of the UST * socket and poll set monitor those by default. + * Listen on POLLIN (even if we never expect any + * data) to ensure that hangup wakes us. */ - ret = lttng_poll_add(&events, ust_cmd.sock, 0); + ret = lttng_poll_add(&events, ust_cmd.sock, LPOLLIN); if (ret < 0) { goto error; } @@ -1165,12 +1261,9 @@ static void *thread_manage_apps(void *data) } error: - DBG("Application communication apps dying"); - close(apps_cmd_pipe[0]); - close(apps_cmd_pipe[1]); - lttng_poll_clean(&events); - +error_poll_create: + DBG("Application communication apps thread cleanup complete"); rcu_thread_offline(); rcu_unregister_thread(); return NULL; @@ -1217,7 +1310,7 @@ static void *thread_dispatch_ust_registration(void *data) ret = write(apps_cmd_pipe[1], ust_cmd, sizeof(struct ust_command)); if (ret < 0) { - perror("write apps cmd pipe"); + PERROR("write apps cmd pipe"); if (errno == EBADF) { /* * We can't inform the application thread to process @@ -1245,7 +1338,7 @@ error: */ static void *thread_registration_apps(void *data) { - int sock = 0, i, ret, pollfd; + int sock = -1, i, ret, pollfd; uint32_t revents, nb_fd; struct lttng_poll_event events; /* @@ -1258,7 +1351,7 @@ static void *thread_registration_apps(void *data) ret = lttcomm_listen_unix_sock(apps_sock); if (ret < 0) { - goto error; + goto error_listen; } /* @@ -1267,13 +1360,13 @@ static void *thread_registration_apps(void *data) */ ret = create_thread_poll_set(&events, 2); if (ret < 0) { - goto error; + goto error_create_poll; } /* Add the application registration socket */ ret = lttng_poll_add(&events, apps_sock, LPOLLIN | LPOLLRDHUP); if (ret < 0) { - goto error; + goto error_poll_add; } /* Notify all applications to register */ @@ -1290,8 +1383,15 @@ static void *thread_registration_apps(void *data) nb_fd = LTTNG_POLL_GETNB(&events); /* Inifinite blocking call, waiting for transmission */ + restart: ret = lttng_poll_wait(&events, -1); if (ret < 0) { + /* + * Restart interrupted system call. + */ + if (errno == EINTR) { + goto restart; + } goto error; } @@ -1320,7 +1420,7 @@ static void *thread_registration_apps(void *data) /* Create UST registration command for enqueuing */ ust_cmd = zmalloc(sizeof(struct ust_command)); if (ust_cmd == NULL) { - perror("ust command zmalloc"); + PERROR("ust command zmalloc"); goto error; } @@ -1332,16 +1432,21 @@ static void *thread_registration_apps(void *data) sizeof(struct ust_register_msg)); if (ret < 0 || ret < sizeof(struct ust_register_msg)) { if (ret < 0) { - perror("lttcomm_recv_unix_sock register apps"); + PERROR("lttcomm_recv_unix_sock register apps"); } else { ERR("Wrong size received on apps register"); } free(ust_cmd); - close(sock); + ret = close(sock); + if (ret) { + PERROR("close"); + } + sock = -1; continue; } ust_cmd->sock = sock; + sock = -1; DBG("UST registration received with pid:%d ppid:%d uid:%d" " gid:%d sock:%d name:%s (version %d.%d)", @@ -1367,16 +1472,28 @@ static void *thread_registration_apps(void *data) } error: - DBG("UST Registration thread dying"); - /* Notify that the registration thread is gone */ notify_ust_apps(0); - close(apps_sock); - close(sock); + if (apps_sock >= 0) { + ret = close(apps_sock); + if (ret) { + PERROR("close"); + } + } + if (sock >= 0) { + ret = close(sock); + if (ret) { + PERROR("close"); + } + } unlink(apps_unix_sock_path); +error_poll_add: lttng_poll_clean(&events); +error_listen: +error_create_poll: + DBG("UST Registration thread cleanup complete"); return NULL; } @@ -1616,17 +1733,17 @@ static pid_t spawn_consumerd(struct consumer_data *consumer_data) break; } default: - perror("unknown consumer type"); + PERROR("unknown consumer type"); exit(EXIT_FAILURE); } if (errno != 0) { - perror("kernel start consumer exec"); + PERROR("kernel start consumer exec"); } exit(EXIT_FAILURE); } else if (pid > 0) { ret = pid; } else { - perror("start consumer fork"); + PERROR("start consumer fork"); ret = -errno; } error: @@ -1717,20 +1834,30 @@ static int init_kernel_tracer(void) error_version: modprobe_remove_lttng_control(); - close(kernel_tracer_fd); - kernel_tracer_fd = 0; + ret = close(kernel_tracer_fd); + if (ret) { + PERROR("close"); + } + kernel_tracer_fd = -1; return LTTCOMM_KERN_VERSION; error_modules: - close(kernel_tracer_fd); + ret = close(kernel_tracer_fd); + if (ret) { + PERROR("close"); + } error_open: modprobe_remove_lttng_control(); error: WARN("No kernel tracer available"); - kernel_tracer_fd = 0; - return LTTCOMM_KERN_NA; + kernel_tracer_fd = -1; + if (!is_root) { + return LTTCOMM_NEED_ROOT_SESSIOND; + } else { + return LTTCOMM_KERN_NA; + } } /* @@ -1743,10 +1870,10 @@ static int init_kernel_tracing(struct ltt_kernel_session *session) if (session->consumer_fds_sent == 0) { /* * Assign default kernel consumer socket if no consumer assigned to the - * kernel session. At this point, it's NOT suppose to be 0 but this is + * kernel session. At this point, it's NOT supposed to be -1 but this is * an extra security check. */ - if (session->consumer_fd == 0) { + if (session->consumer_fd < 0) { session->consumer_fd = kconsumer_data.cmd_sock; } @@ -1834,7 +1961,7 @@ static int create_kernel_session(struct ltt_session *session) } /* Set kernel consumer socket fd */ - if (kconsumer_data.cmd_sock) { + if (kconsumer_data.cmd_sock >= 0) { session->kernel_session->consumer_fd = kconsumer_data.cmd_sock; } @@ -2031,8 +2158,17 @@ static int list_lttng_ust_global_events(char *channel_name, case LTTNG_UST_FUNCTION: tmp[i].type = LTTNG_EVENT_FUNCTION; break; - case LTTNG_UST_TRACEPOINT_LOGLEVEL: - tmp[i].type = LTTNG_EVENT_TRACEPOINT_LOGLEVEL; + } + tmp[i].loglevel = uevent->attr.loglevel; + switch (uevent->attr.loglevel_type) { + case LTTNG_UST_LOGLEVEL_ALL: + tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL; + break; + case LTTNG_UST_LOGLEVEL_RANGE: + tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE; + break; + case LTTNG_UST_LOGLEVEL_SINGLE: + tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE; break; } i++; @@ -2159,11 +2295,11 @@ static int cmd_disable_channel(struct ltt_session *session, } break; } +#if 0 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: case LTTNG_DOMAIN_UST_EXEC_NAME: case LTTNG_DOMAIN_UST_PID: - ret = LTTCOMM_NOT_IMPLEMENTED; - goto error; +#endif default: ret = LTTCOMM_UNKNOWN_DOMAIN; goto error; @@ -2222,11 +2358,11 @@ static int cmd_enable_channel(struct ltt_session *session, } break; } +#if 0 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: case LTTNG_DOMAIN_UST_EXEC_NAME: case LTTNG_DOMAIN_UST_PID: - ret = LTTCOMM_NOT_IMPLEMENTED; - goto error; +#endif default: ret = LTTCOMM_UNKNOWN_DOMAIN; goto error; @@ -2289,11 +2425,13 @@ static int cmd_disable_event(struct ltt_session *session, int domain, channel_name); break; } +#if 0 case LTTNG_DOMAIN_UST_EXEC_NAME: case LTTNG_DOMAIN_UST_PID: case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: +#endif default: - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = LTTCOMM_UND; goto error; } @@ -2356,11 +2494,13 @@ static int cmd_disable_event_all(struct ltt_session *session, int domain, break; } +#if 0 case LTTNG_DOMAIN_UST_EXEC_NAME: case LTTNG_DOMAIN_UST_PID: case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: +#endif default: - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = LTTCOMM_UND; goto error; } @@ -2397,11 +2537,13 @@ static int cmd_add_context(struct ltt_session *session, int domain, } break; } +#if 0 case LTTNG_DOMAIN_UST_EXEC_NAME: case LTTNG_DOMAIN_UST_PID: case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: +#endif default: - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = LTTCOMM_UND; goto error; } @@ -2413,12 +2555,6 @@ error: /* * Command LTTNG_ENABLE_EVENT processed by the client thread. - * - * TODO: currently, both events and loglevels are kept within the same - * namespace for UST global registry/app registery, so if an event - * happen to have the same name as the loglevel (very unlikely though), - * and an attempt is made to enable/disable both in the same session, - * the first to be created will be the only one allowed to exist. */ static int cmd_enable_event(struct ltt_session *session, int domain, char *channel_name, struct lttng_event *event) @@ -2512,11 +2648,13 @@ static int cmd_enable_event(struct ltt_session *session, int domain, } break; } +#if 0 case LTTNG_DOMAIN_UST_EXEC_NAME: case LTTNG_DOMAIN_UST_PID: case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: +#endif default: - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = LTTCOMM_UND; goto error; } @@ -2647,11 +2785,13 @@ static int cmd_enable_event_all(struct ltt_session *session, int domain, break; } +#if 0 case LTTNG_DOMAIN_UST_EXEC_NAME: case LTTNG_DOMAIN_UST_PID: case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: +#endif default: - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = LTTCOMM_UND; goto error; } @@ -2685,7 +2825,7 @@ static ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events) } break; default: - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = LTTCOMM_UND; goto error; } @@ -2730,7 +2870,7 @@ static int cmd_start_trace(struct ltt_session *session) } /* Open kernel metadata stream */ - if (ksession->metadata_stream_fd == 0) { + if (ksession->metadata_stream_fd < 0) { ret = kernel_open_metadata_stream(ksession); if (ret < 0) { ERR("Kernel create metadata stream failed"); @@ -2853,11 +2993,12 @@ error: /* * Command LTTNG_CREATE_SESSION processed by the client thread. */ -static int cmd_create_session(char *name, char *path, struct ucred *creds) +static int cmd_create_session(char *name, char *path, lttng_sock_cred *creds) { int ret; - ret = session_create(name, path, creds->uid, creds->gid); + ret = session_create(name, path, LTTNG_SOCK_GET_UID_CRED(creds), + LTTNG_SOCK_GET_GID_CRED(creds)); if (ret != LTTCOMM_OK) { goto error; } @@ -2886,7 +3027,7 @@ static int cmd_destroy_session(struct ltt_session *session, char *name) */ ret = notify_thread_pipe(kernel_poll_pipe[1]); if (ret < 0) { - perror("write kernel poll pipe"); + PERROR("write kernel poll pipe"); } ret = session_destroy(session); @@ -2914,9 +3055,20 @@ static int cmd_calibrate(int domain, struct lttng_calibrate *calibrate) } break; } + case LTTNG_DOMAIN_UST: + { + struct lttng_ust_calibrate ucalibrate; + + ucalibrate.type = calibrate->type; + ret = ust_app_calibrate_glb(&ucalibrate); + if (ret < 0) { + ret = LTTCOMM_UST_CALIBRATE_FAIL; + goto error; + } + break; + } default: - /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = LTTCOMM_UND; goto error; } @@ -2952,7 +3104,7 @@ static int cmd_register_consumer(struct ltt_session *session, int domain, break; default: /* TODO: Userspace tracing */ - ret = LTTCOMM_NOT_IMPLEMENTED; + ret = LTTCOMM_UND; goto error; } @@ -3028,7 +3180,7 @@ static ssize_t cmd_list_channels(int domain, struct ltt_session *session, break; default: *channels = NULL; - ret = -LTTCOMM_NOT_IMPLEMENTED; + ret = -LTTCOMM_UND; goto error; } @@ -3075,7 +3227,7 @@ static ssize_t cmd_list_events(int domain, struct ltt_session *session, break; } default: - ret = -LTTCOMM_NOT_IMPLEMENTED; + ret = -LTTCOMM_UND; goto error; } @@ -3096,11 +3248,30 @@ static int process_client_msg(struct command_ctx *cmd_ctx) { int ret = LTTCOMM_OK; int need_tracing_session = 1; + int need_domain; DBG("Processing client command %d", cmd_ctx->lsm->cmd_type); - if (opt_no_kernel && cmd_ctx->lsm->domain.type == LTTNG_DOMAIN_KERNEL) { - ret = LTTCOMM_KERN_NA; + switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_CREATE_SESSION: + case LTTNG_DESTROY_SESSION: + case LTTNG_LIST_SESSIONS: + case LTTNG_LIST_DOMAINS: + case LTTNG_START_TRACE: + case LTTNG_STOP_TRACE: + need_domain = 0; + break; + default: + need_domain = 1; + } + + if (opt_no_kernel && need_domain + && cmd_ctx->lsm->domain.type == LTTNG_DOMAIN_KERNEL) { + if (!is_root) { + ret = LTTCOMM_NEED_ROOT_SESSIOND; + } else { + ret = LTTCOMM_KERN_NA; + } goto error; } @@ -3127,8 +3298,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Commands that DO NOT need a session. */ switch (cmd_ctx->lsm->cmd_type) { - case LTTNG_CALIBRATE: case LTTNG_CREATE_SESSION: + case LTTNG_CALIBRATE: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: need_tracing_session = 0; @@ -3153,18 +3324,21 @@ static int process_client_msg(struct command_ctx *cmd_ctx) break; } + if (!need_domain) { + goto skip_domain; + } /* * Check domain type for specific "pre-action". */ switch (cmd_ctx->lsm->domain.type) { case LTTNG_DOMAIN_KERNEL: if (!is_root) { - ret = LTTCOMM_KERN_NA; + ret = LTTCOMM_NEED_ROOT_SESSIOND; goto error; } /* Kernel tracer check */ - if (kernel_tracer_fd == 0) { + if (kernel_tracer_fd == -1) { /* Basically, load kernel tracer modules */ ret = init_kernel_tracer(); if (ret != 0) { @@ -3246,6 +3420,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) default: break; } +skip_domain: /* * Check that the UID or GID match that of the tracing session. @@ -3253,7 +3428,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx) */ if (need_tracing_session) { if (!session_access_ok(cmd_ctx->session, - cmd_ctx->creds.uid, cmd_ctx->creds.gid)) { + LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), + LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds))) { ret = LTTCOMM_EPERM; goto error; } @@ -3280,7 +3456,6 @@ static int process_client_msg(struct command_ctx *cmd_ctx) ret = cmd_disable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type, cmd_ctx->lsm->u.disable.channel_name, cmd_ctx->lsm->u.disable.name); - ret = LTTCOMM_OK; break; } case LTTNG_DISABLE_ALL_EVENT: @@ -3447,12 +3622,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx) unsigned int nr_sessions; session_lock_list(); - nr_sessions = lttng_sessions_count(cmd_ctx->creds.uid, cmd_ctx->creds.gid); - if (nr_sessions == 0) { - ret = LTTCOMM_NO_SESSION; - session_unlock_list(); - goto error; - } + nr_sessions = lttng_sessions_count( + LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), + LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds)); + ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) * nr_sessions); if (ret < 0) { session_unlock_list(); @@ -3461,7 +3634,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Filled the session array */ list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload), - cmd_ctx->creds.uid, cmd_ctx->creds.gid); + LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds), + LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds)); session_unlock_list(); @@ -3508,7 +3682,7 @@ init_setup_error: */ static void *thread_manage_clients(void *data) { - int sock = 0, ret, i, pollfd; + int sock = -1, ret, i, pollfd; uint32_t revents, nb_fd; struct command_ctx *cmd_ctx = NULL; struct lttng_poll_event events; @@ -3541,7 +3715,7 @@ static void *thread_manage_clients(void *data) * Notify parent pid that we are ready to accept command for client side. */ if (opt_sig_parent) { - kill(ppid, SIGCHLD); + kill(ppid, SIGUSR1); } while (1) { @@ -3550,8 +3724,15 @@ static void *thread_manage_clients(void *data) nb_fd = LTTNG_POLL_GETNB(&events); /* Inifinite blocking call, waiting for transmission */ + restart: ret = lttng_poll_wait(&events, -1); if (ret < 0) { + /* + * Restart interrupted system call. + */ + if (errno == EINTR) { + goto restart; + } goto error; } @@ -3591,14 +3772,14 @@ static void *thread_manage_clients(void *data) /* Allocate context command to process the client request */ cmd_ctx = zmalloc(sizeof(struct command_ctx)); if (cmd_ctx == NULL) { - perror("zmalloc cmd_ctx"); + PERROR("zmalloc cmd_ctx"); goto error; } /* Allocate data buffer for reception */ cmd_ctx->lsm = zmalloc(sizeof(struct lttcomm_session_msg)); if (cmd_ctx->lsm == NULL) { - perror("zmalloc cmd_ctx->lsm"); + PERROR("zmalloc cmd_ctx->lsm"); goto error; } @@ -3615,7 +3796,11 @@ static void *thread_manage_clients(void *data) sizeof(struct lttcomm_session_msg), &cmd_ctx->creds); if (ret <= 0) { DBG("Nothing recv() from client... continuing"); - close(sock); + ret = close(sock); + if (ret) { + PERROR("close"); + } + sock = -1; free(cmd_ctx); continue; } @@ -3651,7 +3836,11 @@ static void *thread_manage_clients(void *data) } /* End of transmission */ - close(sock); + ret = close(sock); + if (ret) { + PERROR("close"); + } + sock = -1; clean_command_ctx(&cmd_ctx); } @@ -3659,8 +3848,18 @@ static void *thread_manage_clients(void *data) error: DBG("Client thread dying"); unlink(client_unix_sock_path); - close(client_sock); - close(sock); + if (client_sock >= 0) { + ret = close(client_sock); + if (ret) { + PERROR("close"); + } + } + if (sock >= 0) { + ret = close(sock); + if (ret) { + PERROR("close"); + } + } lttng_poll_clean(&events); clean_command_ctx(&cmd_ctx); @@ -3844,7 +4043,7 @@ static int init_daemon_socket(void) ret = chmod(client_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (ret < 0) { ERR("Set file permissions failed: %s", client_unix_sock_path); - perror("chmod"); + PERROR("chmod"); goto end; } @@ -3861,7 +4060,7 @@ static int init_daemon_socket(void) S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (ret < 0) { ERR("Set file permissions failed: %s", apps_unix_sock_path); - perror("chmod"); + PERROR("chmod"); goto end; } @@ -3876,24 +4075,19 @@ end: */ static int check_existing_daemon(void) { - if (access(client_unix_sock_path, F_OK) < 0 && - access(apps_unix_sock_path, F_OK) < 0) { - return 0; - } - /* Is there anybody out there ? */ if (lttng_session_daemon_alive()) { return -EEXIST; - } else { - return 0; } + + return 0; } /* * Set the tracing group gid onto the client socket. * * Race window between mkdir and chown is OK because we are going from more - * permissive (root.root) to les permissive (root.tracing). + * permissive (root.root) to less permissive (root.tracing). */ static int set_permissions(char *rundir) { @@ -3911,35 +4105,42 @@ static int set_permissions(char *rundir) ret = chown(rundir, 0, gid); if (ret < 0) { ERR("Unable to set group on %s", rundir); - perror("chown"); + PERROR("chown"); + } + + /* Ensure tracing group can search the run dir */ + ret = chmod(rundir, S_IRWXU | S_IXGRP | S_IXOTH); + if (ret < 0) { + ERR("Unable to set permissions on %s", rundir); + PERROR("chmod"); } /* lttng client socket path */ ret = chown(client_unix_sock_path, 0, gid); if (ret < 0) { ERR("Unable to set group on %s", client_unix_sock_path); - perror("chown"); + PERROR("chown"); } /* kconsumer error socket path */ ret = chown(kconsumer_data.err_unix_sock_path, 0, gid); if (ret < 0) { ERR("Unable to set group on %s", kconsumer_data.err_unix_sock_path); - perror("chown"); + PERROR("chown"); } /* 64-bit ustconsumer error socket path */ ret = chown(ustconsumer64_data.err_unix_sock_path, 0, gid); if (ret < 0) { ERR("Unable to set group on %s", ustconsumer64_data.err_unix_sock_path); - perror("chown"); + PERROR("chown"); } /* 32-bit ustconsumer compat32 error socket path */ ret = chown(ustconsumer32_data.err_unix_sock_path, 0, gid); if (ret < 0) { ERR("Unable to set group on %s", ustconsumer32_data.err_unix_sock_path); - perror("chown"); + PERROR("chown"); } DBG("All permissions are set"); @@ -3950,18 +4151,54 @@ end: /* * Create the pipe used to wake up the kernel thread. + * Closed in cleanup(). */ static int create_kernel_poll_pipe(void) { - return pipe2(kernel_poll_pipe, O_CLOEXEC); + int ret, i; + + ret = pipe(kernel_poll_pipe); + if (ret < 0) { + PERROR("kernel poll pipe"); + goto error; + } + + for (i = 0; i < 2; i++) { + ret = fcntl(kernel_poll_pipe[i], F_SETFD, FD_CLOEXEC); + if (ret < 0) { + PERROR("fcntl kernel_poll_pipe"); + goto error; + } + } + +error: + return ret; } /* * Create the application command pipe to wake thread_manage_apps. + * Closed in cleanup(). */ static int create_apps_cmd_pipe(void) { - return pipe2(apps_cmd_pipe, O_CLOEXEC); + int ret, i; + + ret = pipe(apps_cmd_pipe); + if (ret < 0) { + PERROR("apps cmd pipe"); + goto error; + } + + for (i = 0; i < 2; i++) { + ret = fcntl(apps_cmd_pipe[i], F_SETFD, FD_CLOEXEC); + if (ret < 0) { + PERROR("fcntl apps_cmd_pipe"); + goto error; + } + } + +error: + return ret; } /* @@ -3973,7 +4210,7 @@ static int create_lttng_rundir(const char *rundir) DBG3("Creating LTTng run directory: %s", rundir); - ret = mkdir(rundir, S_IRWXU | S_IRWXG ); + ret = mkdir(rundir, S_IRWXU); if (ret < 0) { if (errno != EEXIST) { ERR("Unable to create %s", rundir); @@ -4015,7 +4252,7 @@ static int set_consumer_sockets(struct consumer_data *consumer_data, DBG2("Creating consumer directory: %s", path); - ret = mkdir(path, S_IRWXU | S_IRWXG); + ret = mkdir(path, S_IRWXU); if (ret < 0) { if (errno != EEXIST) { ERR("Failed to create %s", path); @@ -4056,14 +4293,14 @@ static void sighandler(int sig) { switch (sig) { case SIGPIPE: - DBG("SIGPIPE caugth"); + DBG("SIGPIPE caught"); return; case SIGINT: - DBG("SIGINT caugth"); + DBG("SIGINT caught"); stop_threads(); break; case SIGTERM: - DBG("SIGTERM caugth"); + DBG("SIGTERM caught"); stop_threads(); break; default: @@ -4082,7 +4319,7 @@ static int set_signal_handler(void) sigset_t sigset; if ((ret = sigemptyset(&sigset)) < 0) { - perror("sigemptyset"); + PERROR("sigemptyset"); return ret; } @@ -4090,17 +4327,17 @@ static int set_signal_handler(void) sa.sa_mask = sigset; sa.sa_flags = 0; if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) { - perror("sigaction"); + PERROR("sigaction"); return ret; } if ((ret = sigaction(SIGINT, &sa, NULL)) < 0) { - perror("sigaction"); + PERROR("sigaction"); return ret; } if ((ret = sigaction(SIGPIPE, &sa, NULL)) < 0) { - perror("sigaction"); + PERROR("sigaction"); return ret; } @@ -4124,7 +4361,7 @@ static void set_ulimit(void) ret = setrlimit(RLIMIT_NOFILE, &lim); if (ret < 0) { - perror("failed to set open files limit"); + PERROR("failed to set open files limit"); } } @@ -4137,6 +4374,8 @@ int main(int argc, char **argv) void *status; const char *home_path; + init_kernel_workarounds(); + rcu_register_thread(); /* Create thread quit pipe */ @@ -4156,7 +4395,7 @@ int main(int argc, char **argv) if (opt_daemon) { ret = daemon(0, 0); if (ret < 0) { - perror("daemon"); + PERROR("daemon"); goto error; } } @@ -4360,7 +4599,7 @@ int main(int argc, char **argv) ret = pthread_create(&client_thread, NULL, thread_manage_clients, (void *) NULL); if (ret != 0) { - perror("pthread_create clients"); + PERROR("pthread_create clients"); goto exit_client; } @@ -4368,7 +4607,7 @@ int main(int argc, char **argv) ret = pthread_create(&dispatch_thread, NULL, thread_dispatch_ust_registration, (void *) NULL); if (ret != 0) { - perror("pthread_create dispatch"); + PERROR("pthread_create dispatch"); goto exit_dispatch; } @@ -4376,7 +4615,7 @@ int main(int argc, char **argv) ret = pthread_create(®_apps_thread, NULL, thread_registration_apps, (void *) NULL); if (ret != 0) { - perror("pthread_create registration"); + PERROR("pthread_create registration"); goto exit_reg_apps; } @@ -4384,7 +4623,7 @@ int main(int argc, char **argv) ret = pthread_create(&apps_thread, NULL, thread_manage_apps, (void *) NULL); if (ret != 0) { - perror("pthread_create apps"); + PERROR("pthread_create apps"); goto exit_apps; } @@ -4392,47 +4631,47 @@ int main(int argc, char **argv) ret = pthread_create(&kernel_thread, NULL, thread_manage_kernel, (void *) NULL); if (ret != 0) { - perror("pthread_create kernel"); + PERROR("pthread_create kernel"); goto exit_kernel; } ret = pthread_join(kernel_thread, &status); if (ret != 0) { - perror("pthread_join"); + PERROR("pthread_join"); goto error; /* join error, exit without cleanup */ } exit_kernel: ret = pthread_join(apps_thread, &status); if (ret != 0) { - perror("pthread_join"); + PERROR("pthread_join"); goto error; /* join error, exit without cleanup */ } exit_apps: ret = pthread_join(reg_apps_thread, &status); if (ret != 0) { - perror("pthread_join"); + PERROR("pthread_join"); goto error; /* join error, exit without cleanup */ } exit_reg_apps: ret = pthread_join(dispatch_thread, &status); if (ret != 0) { - perror("pthread_join"); + PERROR("pthread_join"); goto error; /* join error, exit without cleanup */ } exit_dispatch: ret = pthread_join(client_thread, &status); if (ret != 0) { - perror("pthread_join"); + PERROR("pthread_join"); goto error; /* join error, exit without cleanup */ } ret = join_consumer_thread(&kconsumer_data); if (ret != 0) { - perror("join_consumer"); + PERROR("join_consumer"); goto error; /* join error, exit without cleanup */ }