static pthread_t kernel_thread;
static pthread_t dispatch_thread;
static pthread_t health_thread;
+static pthread_t ht_cleanup_thread;
/*
* UST registration command queue. This queue is tied with a futex and uses a N
/*
* This first step of the while is to clean this structure which could free
- * non NULL pointers so zero it before the loop.
+ * non NULL pointers so initialize it before the loop.
*/
- memset(&events, 0, sizeof(events));
+ lttng_poll_init(&events);
if (testpoint(thread_manage_kernel)) {
goto error_testpoint;
*/
static void *thread_dispatch_ust_registration(void *data)
{
- int ret;
+ int ret, err = -1;
struct cds_wfq_node *node;
struct ust_command *ust_cmd = NULL;
struct {
struct cds_list_head head;
} *wait_node = NULL, *tmp_wait_node;
+ health_register(HEALTH_TYPE_APP_REG_DISPATCH);
+
+ health_code_update();
+
CDS_LIST_HEAD(wait_queue);
DBG("[thread] Dispatch UST command started");
while (!CMM_LOAD_SHARED(dispatch_thread_exit)) {
+ health_code_update();
+
/* Atomically prepare the queue futex */
futex_nto1_prepare(&ust_cmd_queue.futex);
struct ust_app *app = NULL;
ust_cmd = NULL;
+ health_code_update();
/* Dequeue command for registration */
node = cds_wfq_dequeue_blocking(&ust_cmd_queue.queue);
if (node == NULL) {
wait_node = zmalloc(sizeof(*wait_node));
if (!wait_node) {
PERROR("zmalloc wait_node dispatch");
+ ret = close(ust_cmd->sock);
+ if (ret < 0) {
+ PERROR("close ust sock dispatch %d", ust_cmd->sock);
+ }
+ lttng_fd_put(1, LTTNG_FD_APPS);
free(ust_cmd);
goto error;
}
*/
cds_list_for_each_entry_safe(wait_node, tmp_wait_node,
&wait_queue, head) {
+ health_code_update();
if (wait_node->app->pid == ust_cmd->reg_msg.pid) {
wait_node->app->notify_sock = ust_cmd->sock;
cds_list_del(&wait_node->head);
break;
}
}
+
+ /*
+ * With no application at this stage the received socket is
+ * basically useless so close it before we free the cmd data
+ * structure for good.
+ */
+ if (!app) {
+ ret = close(ust_cmd->sock);
+ if (ret < 0) {
+ PERROR("close ust sock dispatch %d", ust_cmd->sock);
+ }
+ lttng_fd_put(1, LTTNG_FD_APPS);
+ }
free(ust_cmd);
}
rcu_read_unlock();
session_unlock_list();
- } else {
- /* Application manager threads are not available. */
- ret = close(ust_cmd->sock);
- if (ret < 0) {
- PERROR("close ust_cmd sock");
- }
- lttng_fd_put(1, LTTNG_FD_APPS);
}
} while (node != NULL);
+ health_poll_entry();
/* Futex wait on queue. Blocking call on futex() */
futex_nto1_wait(&ust_cmd_queue.futex);
+ health_poll_exit();
}
+ /* Normal exit, no error */
+ err = 0;
error:
/* Clean up wait queue. */
}
DBG("Dispatch thread dying");
+ if (err) {
+ health_error();
+ ERR("Health error occurred in %s", __func__);
+ }
+ health_unregister();
return NULL;
}
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(health_unix_sock_path);
if (sock < 0) {
case LTTNG_HEALTH_CONSUMER:
reply.ret_code = check_consumer_health();
break;
+ case LTTNG_HEALTH_HT_CLEANUP:
+ reply.ret_code = health_check_state(HEALTH_TYPE_HT_CLEANUP);
+ break;
+ case LTTNG_HEALTH_APP_MANAGE_NOTIFY:
+ reply.ret_code = health_check_state(HEALTH_TYPE_APP_MANAGE_NOTIFY);
+ break;
+ case LTTNG_HEALTH_APP_REG_DISPATCH:
+ reply.ret_code = health_check_state(HEALTH_TYPE_APP_REG_DISPATCH);
+ break;
case LTTNG_HEALTH_ALL:
reply.ret_code =
health_check_state(HEALTH_TYPE_APP_MANAGE) &&
health_check_state(HEALTH_TYPE_APP_REG) &&
health_check_state(HEALTH_TYPE_CMD) &&
health_check_state(HEALTH_TYPE_KERNEL) &&
- check_consumer_health();
+ check_consumer_health() &&
+ health_check_state(HEALTH_TYPE_HT_CLEANUP) &&
+ health_check_state(HEALTH_TYPE_APP_MANAGE_NOTIFY) &&
+ health_check_state(HEALTH_TYPE_APP_REG_DISPATCH);
break;
default:
reply.ret_code = LTTNG_ERR_UND;
PERROR("close");
}
}
- if (new_sock >= 0) {
- ret = close(new_sock);
- if (ret) {
- PERROR("close");
- }
- }
lttng_poll_clean(&events);
}
}
+ /* Setup the thread ht_cleanup communication pipe. */
+ if (utils_create_pipe_cloexec(ht_cleanup_pipe) < 0) {
+ goto exit;
+ }
+
/* Setup the thread apps communication pipe. */
if ((ret = utils_create_pipe_cloexec(apps_cmd_pipe)) < 0) {
goto exit;
write_pidfile();
+ /* Create thread to manage the client socket */
+ ret = pthread_create(&ht_cleanup_thread, NULL,
+ thread_ht_cleanup, (void *) NULL);
+ if (ret != 0) {
+ PERROR("pthread_create ht_cleanup");
+ goto exit_ht_cleanup;
+ }
+
/* Create thread to manage the client socket */
ret = pthread_create(&health_thread, NULL,
thread_manage_health, (void *) NULL);
}
exit_health:
+ ret = pthread_join(ht_cleanup_thread, &status);
+ if (ret != 0) {
+ PERROR("pthread_join ht cleanup thread");
+ goto error; /* join error, exit without cleanup */
+ }
+exit_ht_cleanup:
exit:
/*
* cleanup() is called when no other thread is running.