/* * Try connect to session daemon with sock_path. * * Return 0 on success, else -1 */ static int try_connect_sessiond(const char *sock_path) { int ret; /* If socket exist, we check if the daemon listens for connect. */ ret = access(sock_path, F_OK); if (ret < 0) { /* Not alive */ goto error; } ret = lttcomm_connect_unix_sock(sock_path); if (ret < 0) { /* Not alive */ goto error; } ret = lttcomm_close_unix_sock(ret); if (ret < 0) { PERROR("lttcomm_close_unix_sock"); } return 0; error: return -1; }
/* * Connect to the LTTng session daemon. * * On success, return 0. On error, return -1. */ static int connect_sessiond(void) { int ret; /* Don't try to connect if already connected. */ if (connected) { return 0; } ret = set_session_daemon_path(); if (ret < 0) { goto error; } /* Connect to the sesssion daemon */ ret = lttcomm_connect_unix_sock(sessiond_sock_path); if (ret < 0) { goto error; } sessiond_socket = ret; connected = 1; return 0; error: return -1; }
/* * Connect to the LTTng session daemon. * * On success, return 0. On error, return -1. */ static int connect_sessiond(void) { int ret; ret = set_session_daemon_path(); if (ret < 0) { goto error; } /* Connect to the sesssion daemon */ ret = lttcomm_connect_unix_sock(sessiond_sock_path); if (ret < 0) { goto error; } sessiond_socket = ret; connected = 1; return 0; error: return -1; }
/* * Check session daemon health for a specific health component. * * Return 0 if health is OK or else 1 if BAD. * * Any other negative value is a lttng error code which can be translated with * lttng_strerror(). */ int lttng_health_check(enum lttng_health_component c) { int sock, ret; struct lttcomm_health_msg msg; struct lttcomm_health_data reply; /* Connect to the sesssion daemon */ sock = lttcomm_connect_unix_sock(health_sock_path); if (sock < 0) { ret = -LTTNG_ERR_NO_SESSIOND; goto error; } msg.cmd = LTTNG_HEALTH_CHECK; msg.component = c; ret = lttcomm_send_unix_sock(sock, (void *)&msg, sizeof(msg)); if (ret < 0) { ret = -LTTNG_ERR_FATAL; goto close_error; } ret = lttcomm_recv_unix_sock(sock, (void *)&reply, sizeof(reply)); if (ret < 0) { ret = -LTTNG_ERR_FATAL; goto close_error; } ret = reply.ret_code; close_error: close(sock); error: return ret; }
/* * main */ int main(int argc, char **argv) { int ret = 0, retval = 0; void *status; if (set_signal_handler()) { retval = -1; goto exit_set_signal_handler; } /* Parse arguments */ progname = argv[0]; if (parse_args(argc, argv)) { retval = -1; goto exit_options; } /* Daemonize */ if (opt_daemon) { int i; /* * fork * child: setsid, close FD 0, 1, 2, chdir / * parent: exit (if fork is successful) */ ret = daemon(0, 0); if (ret < 0) { PERROR("daemon"); retval = -1; goto exit_options; } /* * We are in the child. Make sure all other file * descriptors are closed, in case we are called with * more opened file descriptors than the standard ones. */ for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) { (void) close(i); } } /* * Starting from here, we can create threads. This needs to be after * lttng_daemonize due to RCU. */ health_consumerd = health_app_create(NR_HEALTH_CONSUMERD_TYPES); if (!health_consumerd) { retval = -1; goto exit_health_consumerd_cleanup; } /* Set up max poll set size */ if (lttng_poll_set_max_size()) { retval = -1; goto exit_init_data; } if (*command_sock_path == '\0') { switch (opt_type) { case LTTNG_CONSUMER_KERNEL: ret = snprintf(command_sock_path, PATH_MAX, DEFAULT_KCONSUMERD_CMD_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); if (ret < 0) { retval = -1; goto exit_init_data; } break; case LTTNG_CONSUMER64_UST: ret = snprintf(command_sock_path, PATH_MAX, DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); if (ret < 0) { retval = -1; goto exit_init_data; } break; case LTTNG_CONSUMER32_UST: ret = snprintf(command_sock_path, PATH_MAX, DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); if (ret < 0) { retval = -1; goto exit_init_data; } break; default: ERR("Unknown consumerd type"); retval = -1; goto exit_init_data; } } /* Init */ if (lttng_consumer_init()) { retval = -1; goto exit_init_data; } /* Initialize communication library */ lttcomm_init(); /* Initialize TCP timeout values */ lttcomm_inet_init(); if (!getuid()) { /* Set limit for open files */ set_ulimit(); } /* create the consumer instance with and assign the callbacks */ ctx = lttng_consumer_create(opt_type, lttng_consumer_read_subbuffer, NULL, lttng_consumer_on_recv_stream, NULL); if (!ctx) { retval = -1; goto exit_init_data; } lttng_consumer_set_command_sock_path(ctx, command_sock_path); if (*error_sock_path == '\0') { switch (opt_type) { case LTTNG_CONSUMER_KERNEL: ret = snprintf(error_sock_path, PATH_MAX, DEFAULT_KCONSUMERD_ERR_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); if (ret < 0) { retval = -1; goto exit_init_data; } break; case LTTNG_CONSUMER64_UST: ret = snprintf(error_sock_path, PATH_MAX, DEFAULT_USTCONSUMERD64_ERR_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); if (ret < 0) { retval = -1; goto exit_init_data; } break; case LTTNG_CONSUMER32_UST: ret = snprintf(error_sock_path, PATH_MAX, DEFAULT_USTCONSUMERD32_ERR_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); if (ret < 0) { retval = -1; goto exit_init_data; } break; default: ERR("Unknown consumerd type"); retval = -1; goto exit_init_data; } } /* Connect to the socket created by lttng-sessiond to report errors */ DBG("Connecting to error socket %s", error_sock_path); ret = lttcomm_connect_unix_sock(error_sock_path); /* * Not a fatal error, but all communication with lttng-sessiond will * fail. */ if (ret < 0) { WARN("Cannot connect to error socket (is lttng-sessiond started?)"); } lttng_consumer_set_error_sock(ctx, ret); /* * Block RT signals used for UST periodical metadata flush and the live * timer in main, and create a dedicated thread to handle these signals. */ if (consumer_signal_init()) { retval = -1; goto exit_init_data; } ctx->type = opt_type; if (utils_create_pipe(health_quit_pipe)) { retval = -1; goto exit_health_pipe; } /* Create thread to manage the client socket */ ret = pthread_create(&health_thread, NULL, thread_manage_health, (void *) NULL); if (ret) { errno = ret; PERROR("pthread_create health"); retval = -1; goto exit_health_thread; } /* * Wait for health thread to be initialized before letting the * sessiond thread reply to the sessiond that we are ready. */ while (uatomic_read(<tng_consumer_ready)) { usleep(100000); } cmm_smp_mb(); /* Read ready before following operations */ /* Create thread to manage channels */ ret = pthread_create(&channel_thread, NULL, consumer_thread_channel_poll, (void *) ctx); if (ret) { errno = ret; PERROR("pthread_create"); retval = -1; goto exit_channel_thread; } /* Create thread to manage the polling/writing of trace metadata */ ret = pthread_create(&metadata_thread, NULL, consumer_thread_metadata_poll, (void *) ctx); if (ret) { errno = ret; PERROR("pthread_create"); retval = -1; goto exit_metadata_thread; } /* Create thread to manage the polling/writing of trace data */ ret = pthread_create(&data_thread, NULL, consumer_thread_data_poll, (void *) ctx); if (ret) { errno = ret; PERROR("pthread_create"); retval = -1; goto exit_data_thread; } /* Create the thread to manage the receive of fd */ ret = pthread_create(&sessiond_thread, NULL, consumer_thread_sessiond_poll, (void *) ctx); if (ret) { errno = ret; PERROR("pthread_create"); retval = -1; goto exit_sessiond_thread; } /* * Create the thread to manage the UST metadata periodic timer and * live timer. */ ret = pthread_create(&metadata_timer_thread, NULL, consumer_timer_thread, (void *) ctx); if (ret) { errno = ret; PERROR("pthread_create"); retval = -1; goto exit_metadata_timer_thread; } ret = pthread_detach(metadata_timer_thread); if (ret) { errno = ret; PERROR("pthread_detach"); retval = -1; goto exit_metadata_timer_detach; } /* * This is where we start awaiting program completion (e.g. through * signal that asks threads to teardown. */ exit_metadata_timer_detach: exit_metadata_timer_thread: ret = pthread_join(sessiond_thread, &status); if (ret) { errno = ret; PERROR("pthread_join sessiond_thread"); retval = -1; } exit_sessiond_thread: ret = pthread_join(data_thread, &status); if (ret) { errno = ret; PERROR("pthread_join data_thread"); retval = -1; } exit_data_thread: ret = pthread_join(metadata_thread, &status); if (ret) { errno = ret; PERROR("pthread_join metadata_thread"); retval = -1; } exit_metadata_thread: ret = pthread_join(channel_thread, &status); if (ret) { errno = ret; PERROR("pthread_join channel_thread"); retval = -1; } exit_channel_thread: ret = pthread_join(health_thread, &status); if (ret) { errno = ret; PERROR("pthread_join health_thread"); retval = -1; } exit_health_thread: utils_close_pipe(health_quit_pipe); exit_health_pipe: exit_init_data: lttng_consumer_destroy(ctx); lttng_consumer_cleanup(); if (health_consumerd) { health_app_destroy(health_consumerd); } exit_health_consumerd_cleanup: exit_options: exit_set_signal_handler: if (!retval) { exit(EXIT_SUCCESS); } else { exit(EXIT_FAILURE); } }
struct lttng_notification_channel *lttng_notification_channel_create( struct lttng_endpoint *endpoint) { int fd, ret; bool is_in_tracing_group = false, is_root = false; char *sock_path = NULL; struct lttng_notification_channel *channel = NULL; if (!endpoint || endpoint != lttng_session_daemon_notification_endpoint) { goto end; } sock_path = zmalloc(LTTNG_PATH_MAX); if (!sock_path) { goto end; } channel = zmalloc(sizeof(struct lttng_notification_channel)); if (!channel) { goto end; } channel->socket = -1; pthread_mutex_init(&channel->lock, NULL); lttng_dynamic_buffer_init(&channel->reception_buffer); CDS_INIT_LIST_HEAD(&channel->pending_notifications.list); is_root = (getuid() == 0); if (!is_root) { is_in_tracing_group = lttng_check_tracing_group(); } if (is_root || is_in_tracing_group) { lttng_ctl_copy_string(sock_path, DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK, LTTNG_PATH_MAX); ret = lttcomm_connect_unix_sock(sock_path); if (ret >= 0) { fd = ret; goto set_fd; } } /* Fallback to local session daemon. */ ret = snprintf(sock_path, LTTNG_PATH_MAX, DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK, utils_get_home_dir()); if (ret < 0 || ret >= LTTNG_PATH_MAX) { goto error; } ret = lttcomm_connect_unix_sock(sock_path); if (ret < 0) { goto error; } fd = ret; set_fd: channel->socket = fd; ret = handshake(channel); if (ret) { goto error; } end: free(sock_path); return channel; error: lttng_notification_channel_destroy(channel); channel = NULL; goto end; }
/* * main */ int main(int argc, char **argv) { int ret = 0; void *status; /* Parse arguments */ progname = argv[0]; parse_args(argc, argv); /* Daemonize */ if (opt_daemon) { int i; /* * fork * child: setsid, close FD 0, 1, 2, chdir / * parent: exit (if fork is successful) */ ret = daemon(0, 0); if (ret < 0) { PERROR("daemon"); goto error; } /* * We are in the child. Make sure all other file * descriptors are closed, in case we are called with * more opened file descriptors than the standard ones. */ for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) { (void) close(i); } } /* Set up max poll set size */ lttng_poll_set_max_size(); if (*command_sock_path == '\0') { switch (opt_type) { case LTTNG_CONSUMER_KERNEL: snprintf(command_sock_path, PATH_MAX, DEFAULT_KCONSUMERD_CMD_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); break; case LTTNG_CONSUMER64_UST: snprintf(command_sock_path, PATH_MAX, DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); break; case LTTNG_CONSUMER32_UST: snprintf(command_sock_path, PATH_MAX, DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); break; default: WARN("Unknown consumerd type"); goto error; } } /* Init */ lttng_consumer_init(); if (!getuid()) { /* Set limit for open files */ set_ulimit(); } /* create the consumer instance with and assign the callbacks */ ctx = lttng_consumer_create(opt_type, lttng_consumer_read_subbuffer, NULL, lttng_consumer_on_recv_stream, NULL); if (ctx == NULL) { goto error; } lttng_consumer_set_command_sock_path(ctx, command_sock_path); if (*error_sock_path == '\0') { switch (opt_type) { case LTTNG_CONSUMER_KERNEL: snprintf(error_sock_path, PATH_MAX, DEFAULT_KCONSUMERD_ERR_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); break; case LTTNG_CONSUMER64_UST: snprintf(error_sock_path, PATH_MAX, DEFAULT_USTCONSUMERD64_ERR_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); break; case LTTNG_CONSUMER32_UST: snprintf(error_sock_path, PATH_MAX, DEFAULT_USTCONSUMERD32_ERR_SOCK_PATH, DEFAULT_LTTNG_RUNDIR); break; default: WARN("Unknown consumerd type"); goto error; } } if (set_signal_handler() < 0) { goto error; } /* Connect to the socket created by lttng-sessiond to report errors */ DBG("Connecting to error socket %s", error_sock_path); ret = lttcomm_connect_unix_sock(error_sock_path); /* not a fatal error, but all communication with lttng-sessiond will fail */ if (ret < 0) { WARN("Cannot connect to error socket (is lttng-sessiond started?)"); } lttng_consumer_set_error_sock(ctx, ret); /* * For UST consumer, we block RT signals used for periodical metadata flush * in main and create a dedicated thread to handle these signals. */ switch (opt_type) { case LTTNG_CONSUMER32_UST: case LTTNG_CONSUMER64_UST: consumer_signal_init(); break; default: break; } ctx->type = opt_type; /* Create thread to manage channels */ ret = pthread_create(&channel_thread, NULL, consumer_thread_channel_poll, (void *) ctx); if (ret != 0) { perror("pthread_create"); goto error; } /* Create thread to manage the polling/writing of trace metadata */ ret = pthread_create(&metadata_thread, NULL, consumer_thread_metadata_poll, (void *) ctx); if (ret != 0) { perror("pthread_create"); goto metadata_error; } /* Create thread to manage the polling/writing of trace data */ ret = pthread_create(&data_thread, NULL, consumer_thread_data_poll, (void *) ctx); if (ret != 0) { perror("pthread_create"); goto data_error; } /* Create the thread to manage the receive of fd */ ret = pthread_create(&sessiond_thread, NULL, consumer_thread_sessiond_poll, (void *) ctx); if (ret != 0) { perror("pthread_create"); goto sessiond_error; } switch (opt_type) { case LTTNG_CONSUMER32_UST: case LTTNG_CONSUMER64_UST: /* Create the thread to manage the metadata periodic timers */ ret = pthread_create(&metadata_timer_thread, NULL, consumer_timer_metadata_thread, (void *) ctx); if (ret != 0) { perror("pthread_create"); goto metadata_timer_error; } ret = pthread_detach(metadata_timer_thread); if (ret) { errno = ret; perror("pthread_detach"); } break; default: break; } metadata_timer_error: ret = pthread_join(sessiond_thread, &status); if (ret != 0) { perror("pthread_join"); goto error; } sessiond_error: ret = pthread_join(data_thread, &status); if (ret != 0) { perror("pthread_join"); goto error; } data_error: ret = pthread_join(metadata_thread, &status); if (ret != 0) { perror("pthread_join"); goto error; } metadata_error: ret = pthread_join(channel_thread, &status); if (ret != 0) { perror("pthread_join"); goto error; } if (!ret) { ret = EXIT_SUCCESS; lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_EXIT_SUCCESS); goto end; } error: ret = EXIT_FAILURE; if (ctx) { lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_EXIT_FAILURE); } end: lttng_consumer_destroy(ctx); lttng_consumer_cleanup(); return ret; }