+ ret = LTTNG_OK;
+ break;
+ }
+ case LTTNG_SESSION_GET_CURRENT_OUTPUT:
+ {
+ struct lttng_session_get_current_output_return output_return;
+
+ memset(&output_return, 0, sizeof(output_return));
+ ret = cmd_session_get_current_output(cmd_ctx->session,
+ &output_return);
+ if (ret < 0) {
+ ret = -ret;
+ goto error;
+ }
+
+ ret = setup_lttng_msg_no_cmd_header(cmd_ctx, &output_return,
+ sizeof(output_return));
+ if (ret < 0) {
+ ret = -ret;
+ goto error;
+ }
+
+ ret = LTTNG_OK;
+ break;
+ }
+ case LTTNG_ROTATION_SET_SCHEDULE:
+ {
+ bool set_schedule;
+ enum lttng_rotation_schedule_type schedule_type;
+ uint64_t value;
+
+ if (cmd_ctx->session->kernel_session && !check_rotate_compatible()) {
+ DBG("Kernel tracer version does not support session rotations");
+ ret = LTTNG_ERR_ROTATION_WRONG_VERSION;
+ goto error;
+ }
+
+ set_schedule = cmd_ctx->lsm->u.rotation_set_schedule.set == 1;
+ schedule_type = (enum lttng_rotation_schedule_type) cmd_ctx->lsm->u.rotation_set_schedule.type;
+ value = cmd_ctx->lsm->u.rotation_set_schedule.value;
+
+ ret = cmd_rotation_set_schedule(cmd_ctx->session,
+ set_schedule,
+ schedule_type,
+ value,
+ notification_thread_handle);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ break;
+ }
+ case LTTNG_SESSION_LIST_ROTATION_SCHEDULES:
+ {
+ struct lttng_session_list_schedules_return schedules = {
+ .periodic.set = !!cmd_ctx->session->rotate_timer_period,
+ .periodic.value = cmd_ctx->session->rotate_timer_period,
+ .size.set = !!cmd_ctx->session->rotate_size,
+ .size.value = cmd_ctx->session->rotate_size,
+ };
+
+ ret = setup_lttng_msg_no_cmd_header(cmd_ctx, &schedules,
+ sizeof(schedules));
+ if (ret < 0) {
+ ret = -ret;
+ goto error;
+ }
+
+ ret = LTTNG_OK;
+ break;
+ }
+ default:
+ ret = LTTNG_ERR_UND;
+ break;
+ }
+
+error:
+ if (cmd_ctx->llm == NULL) {
+ DBG("Missing llm structure. Allocating one.");
+ if (setup_lttng_msg_no_cmd_header(cmd_ctx, NULL, 0) < 0) {
+ goto setup_error;
+ }
+ }
+ /* Set return code */
+ cmd_ctx->llm->ret_code = ret;
+setup_error:
+ if (cmd_ctx->session) {
+ session_unlock(cmd_ctx->session);
+ }
+ if (need_tracing_session) {
+ session_unlock_list();
+ }
+init_setup_error:
+ assert(!rcu_read_ongoing());
+ return ret;
+}
+
+/*
+ * Thread managing health check socket.
+ */
+static void *thread_manage_health(void *data)
+{
+ int sock = -1, new_sock = -1, ret, i, pollfd, err = -1;
+ uint32_t revents, nb_fd;
+ struct lttng_poll_event events;
+ struct health_comm_msg msg;
+ struct health_comm_reply reply;
+
+ DBG("[thread] Manage health check started");
+
+ rcu_register_thread();
+
+ /* We might hit an error path before this is created. */
+ lttng_poll_init(&events);
+
+ /* Create unix socket */
+ sock = lttcomm_create_unix_sock(config.health_unix_sock_path.value);
+ if (sock < 0) {
+ ERR("Unable to create health check Unix socket");
+ goto error;
+ }
+
+ if (is_root) {
+ /* lttng health client socket path permissions */
+ ret = chown(config.health_unix_sock_path.value, 0,
+ utils_get_group_id(config.tracing_group_name.value));
+ if (ret < 0) {
+ ERR("Unable to set group on %s", config.health_unix_sock_path.value);
+ PERROR("chown");
+ goto error;
+ }
+
+ ret = chmod(config.health_unix_sock_path.value,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (ret < 0) {
+ ERR("Unable to set permissions on %s", config.health_unix_sock_path.value);
+ PERROR("chmod");
+ goto error;
+ }
+ }
+
+ /*