#include "fd-limit.h"
#include "filter.h"
#include "health.h"
+#include "testpoint.h"
#define CONSUMERD_FILE "lttng-consumerd"
ERR("Unable to clean %s", rundir);
}
free(cmd);
+ free(rundir);
DBG("Cleaning up all sessions");
DBG("Thread manage kernel started");
+ testpoint(thread_manage_kernel);
+
health_code_update(&health_thread_kernel);
+ testpoint(thread_manage_kernel_before_loop);
+
ret = create_thread_poll_set(&events, 2);
if (ret < 0) {
goto error_poll_create;
DBG("[thread] Manage consumer started");
+ /*
+ * Since the consumer thread can be spawned at any moment in time, we init
+ * the health to a poll status (1, which is a valid health over time).
+ * When the thread starts, we update here the health to a "code" path being
+ * an even value so this thread, when reaching a poll wait, does not
+ * trigger an error with an even value.
+ *
+ * Here is the use case we avoid.
+ *
+ * +1: the first poll update during initialization (main())
+ * +2 * x: multiple code update once in this thread.
+ * +1: poll wait in this thread (being a good health state).
+ * == even number which after the wait period shows as a bad health.
+ *
+ * In a nutshell, the following poll update to the health state brings back
+ * the state to an even value meaning a code path.
+ */
+ health_poll_update(&consumer_data->health);
+
health_code_update(&consumer_data->health);
ret = lttcomm_listen_unix_sock(consumer_data->err_sock);
/* Inifinite blocking call, waiting for transmission */
restart:
health_poll_update(&consumer_data->health);
+
+ testpoint(thread_manage_consumer);
+
ret = lttng_poll_wait(&events, -1);
health_poll_update(&consumer_data->health);
if (ret < 0) {
DBG("[thread] Manage application started");
+ testpoint(thread_manage_apps);
+
rcu_register_thread();
rcu_thread_online();
goto error;
}
+ testpoint(thread_manage_apps_before_loop);
+
health_code_update(&health_thread_app_manage);
while (1) {
ust_app_unregister(ust_cmd.sock);
} else {
/*
- * 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.
+ * We only monitor the error events of the socket. This
+ * thread does not handle any incoming data from UST
+ * (POLLIN).
*/
- ret = lttng_poll_add(&events, ust_cmd.sock, LPOLLIN);
+ ret = lttng_poll_add(&events, ust_cmd.sock,
+ LPOLLERR & LPOLLHUP & LPOLLRDHUP);
if (ret < 0) {
goto error;
}
DBG("[thread] Manage application registration started");
+ testpoint(thread_registration_apps);
+
ret = lttcomm_listen_unix_sock(apps_sock);
if (ret < 0) {
goto error_listen;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
DBG3("Copying tracing session consumer output in kernel session");
+ /*
+ * XXX: We should audit the session creation and what this function
+ * does "extra" in order to avoid a destroy since this function is used
+ * in the domain session creation (kernel and ust) only. Same for UST
+ * domain.
+ */
+ if (session->kernel_session->consumer) {
+ consumer_destroy_output(session->kernel_session->consumer);
+ }
session->kernel_session->consumer =
consumer_copy_output(session->consumer);
/* Ease our life a bit for the next part */
break;
case LTTNG_DOMAIN_UST:
DBG3("Copying tracing session consumer output in UST session");
+ if (session->ust_session->consumer) {
+ consumer_destroy_output(session->ust_session->consumer);
+ }
session->ust_session->consumer =
consumer_copy_output(session->consumer);
/* Ease our life a bit for the next part */
case LTTNG_LIST_DOMAINS:
case LTTNG_START_TRACE:
case LTTNG_STOP_TRACE:
+ case LTTNG_DATA_PENDING:
need_domain = 0;
break;
default:
DBG("No URIs received from client... continuing");
*sock_error = 1;
ret = LTTNG_ERR_SESSION_FAIL;
+ free(uris);
goto error;
}
ret = cmd_set_consumer_uri(cmd_ctx->lsm->domain.type, cmd_ctx->session,
nb_uri, uris);
if (ret != LTTNG_OK) {
+ free(uris);
goto error;
}
}
}
+ free(uris);
+
break;
}
case LTTNG_START_TRACE:
DBG("No URIs received from client... continuing");
*sock_error = 1;
ret = LTTNG_ERR_SESSION_FAIL;
+ free(uris);
goto error;
}
if (nb_uri == 1 && uris[0].dtype != LTTNG_DST_PATH) {
DBG("Creating session with ONE network URI is a bad call");
ret = LTTNG_ERR_SESSION_FAIL;
+ free(uris);
goto error;
}
}
ret = cmd_create_session_uri(cmd_ctx->lsm->session.name, uris, nb_uri,
&cmd_ctx->creds);
+ free(uris);
+
break;
}
case LTTNG_DESTROY_SESSION:
bytecode);
break;
}
+ case LTTNG_DATA_PENDING:
+ {
+ ret = cmd_data_pending(cmd_ctx->session);
+ break;
+ }
default:
ret = LTTNG_ERR_UND;
break;
DBG("[thread] Manage client started");
+ testpoint(thread_manage_clients);
+
rcu_register_thread();
health_code_update(&health_thread_cmd);
kill(ppid, SIGUSR1);
}
+ testpoint(thread_manage_clients_before_loop);
+
health_code_update(&health_thread_cmd);
while (1) {
/*
* Init health counters of the consumer thread. We do a quick hack here to
* the state of the consumer health is fine even if the thread is not
- * started. This is simply to ease our life and has no cost what so ever.
+ * started. Once the thread starts, the health state is updated with a poll
+ * value to set a health code path. This is simply to ease our life and has
+ * no cost what so ever.
*/
health_init(&kconsumer_data.health);
health_poll_update(&kconsumer_data.health);
goto error; /* join error, exit without cleanup */
}
+ ret = join_consumer_thread(&ustconsumer32_data);
+ if (ret != 0) {
+ PERROR("join_consumer ust32");
+ goto error; /* join error, exit without cleanup */
+ }
+
+ ret = join_consumer_thread(&ustconsumer64_data);
+ if (ret != 0) {
+ PERROR("join_consumer ust64");
+ goto error; /* join error, exit without cleanup */
+ }
+
exit_client:
+ ret = pthread_join(health_thread, &status);
+ if (ret != 0) {
+ PERROR("pthread_join health thread");
+ goto error; /* join error, exit without cleanup */
+ }
+
exit_health:
exit:
/*