X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmain.c;h=e341233ff0ae6cee85e04f85788716ef476779b2;hb=768102358c0646342496b2b07b4518e0d5258b6f;hp=6c4b8ec5ce4c94a26b14c33f44839938f8bdd7ac;hpb=4ee14516054068e38d7dc5dbeaccd39151ca2d06;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 6c4b8ec5c..e341233ff 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 @@ -75,20 +75,18 @@ struct consumer_data { char cmd_unix_sock_path[PATH_MAX]; }; +#include "benchmark.h" + /* Const values */ const char default_home_dir[] = DEFAULT_HOME_DIR; 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; -/* Variables */ -int opt_verbose; /* Not static for lttngerr.h */ -int opt_verbose_consumer; /* Not static for lttngerr.h */ -int opt_quiet; /* Not static for lttngerr.h */ - const char *progname; const char *opt_tracing_group; static int opt_sig_parent; +static int opt_verbose_consumer; static int opt_daemon; static int opt_no_kernel; static int is_root; /* Set to 1 if the daemon is running as root */ @@ -100,16 +98,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 +126,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; @@ -295,14 +299,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; } @@ -324,7 +336,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); } @@ -378,7 +391,7 @@ static void stop_threads(void) */ static void cleanup(void) { - int ret; + int ret, i; char *cmd; struct ltt_session *sess, *stmp; @@ -419,13 +432,63 @@ 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"); + } + } + } + + /* OUTPUT BENCHMARK RESULTS */ + bench_init(); + + if (getenv("BENCH_UST_NOTIFY")) { + bench_print_ust_notification(); + } + + if (getenv("BENCH_UST_REGISTER")) { + bench_print_ust_register(); + bench_print_ust_unregister(); + } + + if (getenv("BENCH_BOOT_PROCESS")) { + bench_print_boot_process(); + } + + bench_close(); + /* END BENCHMARK */ /* */ DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm" @@ -489,7 +552,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 +574,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 +605,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 +619,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 +637,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; } } @@ -615,9 +678,13 @@ static int notify_ust_apps(int active) goto error; } + tracepoint(ust_notify_apps_start); + /* Wake waiting process */ futex_wait_update((int32_t *) wait_shm_mmap, active); + tracepoint(ust_notify_apps_stop); + /* Apps notified successfully */ return 0; @@ -640,7 +707,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 +788,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; } @@ -796,11 +863,13 @@ static void *thread_manage_kernel(void *data) char tmp; struct lttng_poll_event events; + tracepoint(sessiond_th_kern_start); + DBG("Thread manage kernel started"); 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); @@ -830,9 +899,18 @@ static void *thread_manage_kernel(void *data) /* Zeroed the poll events */ lttng_poll_reset(&events); + tracepoint(sessiond_th_kern_poll); + /* 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 */ @@ -878,12 +956,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; } @@ -892,17 +967,19 @@ 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; struct consumer_data *consumer_data = data; + tracepoint(sessiond_th_kcon_start); + DBG("[thread] Manage consumer started"); ret = lttcomm_listen_unix_sock(consumer_data->err_sock); if (ret < 0) { - goto error; + goto error_listen; } /* @@ -911,7 +988,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); @@ -921,9 +998,18 @@ static void *thread_manage_consumer(void *data) nb_fd = LTTNG_POLL_GETNB(&events); + tracepoint(sessiond_th_kcon_poll); + /* 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; } @@ -993,8 +1079,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; } @@ -1029,16 +1122,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; } @@ -1053,6 +1163,8 @@ static void *thread_manage_apps(void *data) struct ust_command ust_cmd; struct lttng_poll_event events; + tracepoint(sessiond_th_apps_start); + DBG("[thread] Manage application started"); rcu_register_thread(); @@ -1060,7 +1172,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); @@ -1076,9 +1188,18 @@ static void *thread_manage_apps(void *data) DBG("Apps thread polling on %d fds", nb_fd); + tracepoint(sessiond_th_apps_poll); + /* 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; } @@ -1099,13 +1220,17 @@ static void *thread_manage_apps(void *data) ERR("Apps command pipe error"); goto error; } else if (revents & LPOLLIN) { + system("sysctl vm.drop_caches=3"); + tracepoint(ust_register_read_start); /* 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; } + tracepoint(ust_register_read_stop); + tracepoint(ust_register_add_start); /* Register applicaton to the session daemon */ ret = ust_app_register(&ust_cmd.reg_msg, ust_cmd.sock); @@ -1114,6 +1239,7 @@ static void *thread_manage_apps(void *data) } else if (ret < 0) { break; } + tracepoint(ust_register_add_stop); /* * Validate UST version compatibility. @@ -1127,6 +1253,7 @@ static void *thread_manage_apps(void *data) update_ust_app(ust_cmd.sock); } + tracepoint(ust_register_done_start); ret = ust_app_register_done(ust_cmd.sock); if (ret < 0) { /* @@ -1135,11 +1262,14 @@ static void *thread_manage_apps(void *data) */ ust_app_unregister(ust_cmd.sock); } else { + tracepoint(ust_register_done_stop); /* * 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; } @@ -1147,7 +1277,6 @@ static void *thread_manage_apps(void *data) DBG("Apps with sock %d added to poll set", ust_cmd.sock); } - break; } } else { @@ -1156,6 +1285,8 @@ static void *thread_manage_apps(void *data) * the event at poll_wait. */ if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) { + tracepoint(ust_unregister_start); + /* Removing from the poll set */ ret = lttng_poll_del(&events, pollfd); if (ret < 0) { @@ -1164,6 +1295,8 @@ static void *thread_manage_apps(void *data) /* Socket closed on remote end. */ ust_app_unregister(pollfd); + + tracepoint(ust_unregister_stop); break; } } @@ -1171,12 +1304,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; @@ -1192,6 +1322,8 @@ static void *thread_dispatch_ust_registration(void *data) struct cds_wfq_node *node; struct ust_command *ust_cmd = NULL; + tracepoint(sessiond_th_dispatch_start); + DBG("[thread] Dispatch UST command started"); while (!dispatch_thread_exit) { @@ -1199,6 +1331,8 @@ static void *thread_dispatch_ust_registration(void *data) futex_nto1_prepare(&ust_cmd_queue.futex); do { + tracepoint(sessiond_th_dispatch_block); + /* Dequeue command for registration */ node = cds_wfq_dequeue_blocking(&ust_cmd_queue.queue); if (node == NULL) { @@ -1207,6 +1341,8 @@ static void *thread_dispatch_ust_registration(void *data) break; } + tracepoint(ust_dispatch_register_start); + ust_cmd = caa_container_of(node, struct ust_command, node); DBG("Dispatching UST registration pid:%d ppid:%d uid:%d" @@ -1223,7 +1359,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 @@ -1237,6 +1373,8 @@ static void *thread_dispatch_ust_registration(void *data) free(ust_cmd); } while (node != NULL); + tracepoint(ust_dispatch_register_stop); + /* Futex wait on queue. Blocking call on futex() */ futex_nto1_wait(&ust_cmd_queue.futex); } @@ -1251,7 +1389,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; /* @@ -1260,11 +1398,13 @@ static void *thread_registration_apps(void *data) */ struct ust_command *ust_cmd = NULL; + tracepoint(sessiond_th_reg_start); + DBG("[thread] Manage application registration started"); ret = lttcomm_listen_unix_sock(apps_sock); if (ret < 0) { - goto error; + goto error_listen; } /* @@ -1273,13 +1413,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 */ @@ -1293,11 +1433,20 @@ static void *thread_registration_apps(void *data) while (1) { DBG("Accepting application registration"); + tracepoint(sessiond_th_reg_poll); + 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; } @@ -1318,6 +1467,9 @@ static void *thread_registration_apps(void *data) ERR("Register apps socket poll error"); goto error; } else if (revents & LPOLLIN) { + /* Registration starts here. Recording cycles */ + tracepoint(ust_register_start); + sock = lttcomm_accept_unix_sock(apps_sock); if (sock < 0) { goto error; @@ -1326,7 +1478,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; } @@ -1338,16 +1490,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,22 +1524,36 @@ static void *thread_registration_apps(void *data) * barrier with the exchange in cds_wfq_enqueue. */ futex_nto1_wake(&ust_cmd_queue.futex); + + tracepoint(ust_register_stop); } } } } 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; } @@ -1622,17 +1793,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: @@ -1723,20 +1894,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; + } } /* @@ -1749,10 +1930,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; } @@ -1840,7 +2021,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; } @@ -2729,7 +2910,8 @@ static int cmd_start_trace(struct ltt_session *session) usess = session->ust_session; if (session->enabled) { - ret = LTTCOMM_UST_START_FAIL; + /* Already started. */ + ret = LTTCOMM_TRACE_ALREADY_STARTED; goto error; } @@ -2749,7 +2931,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"); @@ -2821,7 +3003,7 @@ static int cmd_stop_trace(struct ltt_session *session) usess = session->ust_session; if (!session->enabled) { - ret = LTTCOMM_UST_STOP_FAIL; + ret = LTTCOMM_TRACE_ALREADY_STOPPED; goto error; } @@ -2872,11 +3054,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; } @@ -2905,7 +3088,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); @@ -3126,11 +3309,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; } @@ -3157,8 +3359,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; @@ -3183,18 +3385,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) { @@ -3276,6 +3481,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. @@ -3283,7 +3489,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; } @@ -3384,14 +3591,18 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } case LTTNG_CREATE_SESSION: { + tracepoint(create_session_start); ret = cmd_create_session(cmd_ctx->lsm->session.name, cmd_ctx->lsm->session.path, &cmd_ctx->creds); + tracepoint(create_session_end); break; } case LTTNG_DESTROY_SESSION: { + tracepoint(destroy_session_start); ret = cmd_destroy_session(cmd_ctx->session, cmd_ctx->lsm->session.name); + tracepoint(destroy_session_end); break; } case LTTNG_LIST_DOMAINS: @@ -3476,12 +3687,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(); @@ -3490,7 +3699,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(); @@ -3537,11 +3747,13 @@ 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; + tracepoint(sessiond_th_cli_start); + DBG("[thread] Manage client started"); rcu_register_thread(); @@ -3576,11 +3788,20 @@ static void *thread_manage_clients(void *data) while (1) { DBG("Accepting client command ..."); + tracepoint(sessiond_th_cli_poll); + 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; } @@ -3620,14 +3841,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; } @@ -3644,7 +3865,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; } @@ -3680,7 +3905,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); } @@ -3688,8 +3917,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); @@ -3818,11 +4057,11 @@ static int parse_args(int argc, char **argv) opt_no_kernel = 1; break; case 'q': - opt_quiet = 1; + lttng_opt_quiet = 1; break; case 'v': /* Verbose level can increase using multiple -v */ - opt_verbose += 1; + lttng_opt_verbose += 1; break; case 'Z': opt_verbose_consumer += 1; @@ -3873,7 +4112,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; } @@ -3890,7 +4129,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; } @@ -3917,7 +4156,7 @@ static int check_existing_daemon(void) * 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) { @@ -3935,35 +4174,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"); @@ -3974,18 +4220,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; } /* @@ -3997,7 +4279,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); @@ -4039,13 +4321,14 @@ 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) { + PERROR("mkdir"); ERR("Failed to create %s", path); goto error; } - ret = 0; + ret = -1; } /* Create the kconsumerd error unix socket */ @@ -4106,7 +4389,7 @@ static int set_signal_handler(void) sigset_t sigset; if ((ret = sigemptyset(&sigset)) < 0) { - perror("sigemptyset"); + PERROR("sigemptyset"); return ret; } @@ -4114,17 +4397,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; } @@ -4148,7 +4431,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"); } } @@ -4161,6 +4444,8 @@ int main(int argc, char **argv) void *status; const char *home_path; + tracepoint(sessiond_boot_start); + init_kernel_workarounds(); rcu_register_thread(); @@ -4182,7 +4467,7 @@ int main(int argc, char **argv) if (opt_daemon) { ret = daemon(0, 0); if (ret < 0) { - perror("daemon"); + PERROR("daemon"); goto error; } } @@ -4386,7 +4671,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; } @@ -4394,7 +4679,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; } @@ -4402,7 +4687,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; } @@ -4410,7 +4695,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; } @@ -4418,47 +4703,49 @@ 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; } + tracepoint(sessiond_boot_end); + 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 */ }