+ /* Signal condition to tell that the kconsumerd is ready */
+ sem_post(&kconsumerd_sem);
+ DBG("Kconsumerd command socket ready");
+ } else {
+ DBG("Kconsumerd error when waiting for SOCK_READY : %s",
+ lttcomm_get_readable_code(-code));
+ goto error;
+ }
+
+ /* Remove the kconsumerd error socket since we have established a connexion */
+ ret = lttng_poll_del(&events, kconsumerd_err_sock);
+ if (ret < 0) {
+ goto error;
+ }
+
+ ret = lttng_poll_add(&events, sock, LPOLLIN | LPOLLRDHUP);
+ if (ret < 0) {
+ goto error;
+ }
+
+ /* Update number of fd */
+ nb_fd = LTTNG_POLL_GETNB(&events);
+
+ /* Inifinite blocking call, waiting for transmission */
+ ret = lttng_poll_wait(&events, -1);
+ if (ret < 0) {
+ goto error;
+ }
+
+ for (i = 0; i < nb_fd; i++) {
+ /* Fetch once the poll data */
+ revents = LTTNG_POLL_GETEV(&events, i);
+ pollfd = LTTNG_POLL_GETFD(&events, i);
+
+ /* Thread quit pipe has been closed. Killing thread. */
+ ret = check_thread_quit_pipe(pollfd, revents);
+ if (ret) {
+ goto error;
+ }
+
+ /* Event on the kconsumerd socket */
+ if (pollfd == sock) {
+ if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+ ERR("Kconsumerd err socket second poll error");
+ goto error;
+ }
+ }
+ }
+
+ /* Wait for any kconsumerd error */
+ ret = lttcomm_recv_unix_sock(sock, &code, sizeof(enum lttcomm_return_code));
+ if (ret <= 0) {
+ ERR("Kconsumerd closed the command socket");
+ goto error;
+ }
+
+ ERR("Kconsumerd return code : %s", lttcomm_get_readable_code(-code));
+
+error:
+ DBG("Kconsumerd thread dying");
+ close(kconsumerd_err_sock);
+ close(kconsumerd_cmd_sock);
+ close(sock);
+
+ unlink(kconsumerd_err_unix_sock_path);
+ unlink(kconsumerd_cmd_unix_sock_path);
+ kconsumerd_pid = 0;
+
+ lttng_poll_clean(&events);
+
+ return NULL;
+}
+
+/*
+ * This thread manage application communication.
+ */
+static void *thread_manage_apps(void *data)
+{
+ int i, ret, pollfd;
+ uint32_t revents, nb_fd;
+ struct ust_command ust_cmd;
+ struct lttng_poll_event events;
+
+ DBG("[thread] Manage application started");
+
+ ret = create_thread_poll_set(&events, 2);
+ if (ret < 0) {
+ goto error;
+ }
+
+ ret = lttng_poll_add(&events, apps_cmd_pipe[0], LPOLLIN | LPOLLRDHUP);
+ if (ret < 0) {
+ goto error;
+ }
+
+ while (1) {
+ /* Zeroed the events structure */
+ lttng_poll_reset(&events);
+
+ nb_fd = LTTNG_POLL_GETNB(&events);
+
+ DBG("Apps thread polling on %d fds", nb_fd);
+
+ /* Inifinite blocking call, waiting for transmission */
+ ret = lttng_poll_wait(&events, -1);
+ if (ret < 0) {
+ goto error;
+ }
+
+ for (i = 0; i < nb_fd; i++) {
+ /* Fetch once the poll data */
+ revents = LTTNG_POLL_GETEV(&events, i);
+ pollfd = LTTNG_POLL_GETFD(&events, i);
+
+ /* Thread quit pipe has been closed. Killing thread. */
+ ret = check_thread_quit_pipe(pollfd, revents);
+ if (ret) {
+ goto error;
+ }
+
+ /* Inspect the apps cmd pipe */
+ if (pollfd == apps_cmd_pipe[0]) {
+ if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+ ERR("Apps command pipe error");
+ goto error;
+ } else if (revents & LPOLLIN) {
+ /* 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");
+ goto error;
+ }
+
+ /* Register applicaton to the session daemon */
+ ret = register_traceable_app(&ust_cmd.reg_msg, ust_cmd.sock);
+ if (ret < 0) {
+ /* Only critical ENOMEM error can be returned here */
+ goto error;
+ }
+
+ ret = ustctl_register_done(ust_cmd.sock);
+ if (ret < 0) {
+ /*
+ * If the registration is not possible, we simply
+ * unregister the apps and continue
+ */
+ unregister_traceable_app(ust_cmd.sock);
+ } else {
+ /*
+ * We just need here to monitor the close of the UST
+ * socket and poll set monitor those by default.
+ */
+ ret = lttng_poll_add(&events, ust_cmd.sock, 0);
+ if (ret < 0) {
+ goto error;
+ }
+
+ DBG("Apps with sock %d added to poll set", ust_cmd.sock);
+ }
+ break;
+ }
+ } else {
+ /*
+ * At this point, we know that a registered application made the
+ * event at poll_wait.
+ */
+ if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+ /* Removing from the poll set */
+ ret = lttng_poll_del(&events, pollfd);
+ if (ret < 0) {
+ goto error;
+ }
+
+ /* Socket closed */
+ unregister_traceable_app(pollfd);
+ break;
+ }
+ }
+ }