#include <sys/types.h>
#include <unistd.h>
#include <urcu/compiler.h>
-#include <lttng/ust-error.h>
#include <signal.h>
#include <common/common.h>
#include "health-sessiond.h"
#include "ust-app.h"
#include "ust-consumer.h"
-#include "ust-ctl.h"
+#include "lttng-ust-ctl.h"
+#include "lttng-ust-error.h"
#include "utils.h"
#include "session.h"
#include "lttng-sessiond.h"
#include "notification-thread-commands.h"
#include "rotate.h"
+struct lttng_ht *ust_app_ht;
+struct lttng_ht *ust_app_ht_by_sock;
+struct lttng_ht *ust_app_ht_by_notify_sock;
+
static
int ust_app_flush_app_session(struct ust_app *app, struct ust_app_session *ua_sess);
* nullified. The session lock MUST be held unless the application is
* in the destroy path.
*
+ * Do not hold the registry lock while communicating with the consumerd, because
+ * doing so causes inter-process deadlocks between consumerd and sessiond with
+ * the metadata request notification.
+ *
* Return 0 on success else a negative value.
*/
static int close_metadata(struct ust_registry_session *registry,
{
int ret;
struct consumer_socket *socket;
+ uint64_t metadata_key;
+ bool registry_was_already_closed;
assert(registry);
assert(consumer);
rcu_read_lock();
pthread_mutex_lock(®istry->lock);
+ metadata_key = registry->metadata_key;
+ registry_was_already_closed = registry->metadata_closed;
+ if (metadata_key != 0) {
+ /*
+ * Metadata closed. Even on error this means that the consumer
+ * is not responding or not found so either way a second close
+ * should NOT be emit for this registry.
+ */
+ registry->metadata_closed = 1;
+ }
+ pthread_mutex_unlock(®istry->lock);
- if (!registry->metadata_key || registry->metadata_closed) {
+ if (metadata_key == 0 || registry_was_already_closed) {
ret = 0;
goto end;
}
consumer);
if (!socket) {
ret = -1;
- goto error;
+ goto end;
}
- ret = consumer_close_metadata(socket, registry->metadata_key);
+ ret = consumer_close_metadata(socket, metadata_key);
if (ret < 0) {
- goto error;
+ goto end;
}
-error:
- /*
- * Metadata closed. Even on error this means that the consumer is not
- * responding or not found so either way a second close should NOT be emit
- * for this registry.
- */
- registry->metadata_closed = 1;
end:
- pthread_mutex_unlock(®istry->lock);
rcu_read_unlock();
return ret;
}
/* Init most of the default value by allocating and zeroing */
ua_event = zmalloc(sizeof(struct ust_app_event));
if (ua_event == NULL) {
- PERROR("malloc");
+ PERROR("Failed to allocate ust_app_event structure");
goto error;
}
app->byte_order, app->version.major, app->version.minor,
reg_pid->root_shm_path, reg_pid->shm_path,
ua_sess->effective_credentials.uid,
- ua_sess->effective_credentials.gid);
+ ua_sess->effective_credentials.gid, ua_sess->tracing_id,
+ app->uid);
if (ret < 0) {
/*
* reg_pid->registry->reg.ust is NULL upon error, so we need to
app->uint64_t_alignment, app->long_alignment,
app->byte_order, app->version.major,
app->version.minor, reg_uid->root_shm_path,
- reg_uid->shm_path, usess->uid, usess->gid);
+ reg_uid->shm_path, usess->uid, usess->gid,
+ ua_sess->tracing_id, app->uid);
if (ret < 0) {
/*
* reg_uid->registry->reg.ust is NULL upon error, so we need to
ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr);
if (ua_event == NULL) {
- /* Only malloc can failed so something is really wrong */
+ /* Only failure mode of alloc_ust_app_event(). */
ret = -ENOMEM;
goto end;
}
/* Create it on the tracer side */
ret = create_ust_event(app, ua_sess, ua_chan, ua_event);
if (ret < 0) {
- /* Not found previously means that it does not exist on the tracer */
- assert(ret != -LTTNG_UST_ERR_EXIST);
+ /*
+ * Not found previously means that it does not exist on the
+ * tracer. If the application reports that the event existed,
+ * it means there is a bug in the sessiond or lttng-ust
+ * (or corruption, etc.)
+ */
+ if (ret == -LTTNG_UST_ERR_EXIST) {
+ ERR("Tracer for application reported that an event being created already existed: "
+ "event_name = \"%s\", pid = %d, ppid = %d, uid = %d, gid = %d",
+ uevent->attr.name,
+ app->pid, app->ppid, app->uid,
+ app->gid);
+ }
goto error;
}
ret = ust_app_channel_allocate(ua_sess, uchan,
LTTNG_UST_CHAN_PER_CPU, usess,
&ua_chan);
- if (ret == 0) {
- ret = ust_app_channel_send(app, usess,
- ua_sess, ua_chan);
- } else {
- goto end;
+ if (ret < 0) {
+ goto error;
+ }
+
+ ret = ust_app_channel_send(app, usess,
+ ua_sess, ua_chan);
+ if (ret) {
+ goto error;
}
/* Add contexts. */
ret = create_ust_app_channel_context(ua_chan,
&uctx->ctx, app);
if (ret) {
- goto end;
+ goto error;
}
}
}
+
+error:
if (ret < 0) {
switch (ret) {
case -ENOTCONN:
break;
}
}
-end:
+
if (ret == 0 && _ua_chan) {
/*
* Only return the application's channel on success. Note
if (session_was_created) {
destroy_app_session(app, ua_sess);
}
- goto error_rcu_unlock;
+ /* Continue to the next application. */
}
}
enum lttng_error_code status = LTTNG_OK;
struct lttng_ht_iter iter;
struct ust_app *app;
+ char *trace_path = NULL;
assert(usess);
assert(output);
cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
struct buffer_reg_channel *reg_chan;
struct consumer_socket *socket;
- char *trace_path = NULL;
char pathname[PATH_MAX];
if (!reg->registry->reg.ust->metadata_key) {
status = LTTNG_ERR_INVALID;
goto error;
}
+ /* Free path allowed on previous iteration. */
+ free(trace_path);
trace_path = setup_channel_trace_path(usess->consumer, pathname);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
usess->gid, trace_path, wait,
nb_packets_per_stream);
if (status != LTTNG_OK) {
- free(trace_path);
goto error;
}
}
status = consumer_snapshot_channel(socket,
reg->registry->reg.ust->metadata_key, output, 1,
usess->uid, usess->gid, trace_path, wait, 0);
- free(trace_path);
if (status != LTTNG_OK) {
goto error;
}
struct ust_app_channel *ua_chan;
struct ust_app_session *ua_sess;
struct ust_registry_session *registry;
- char *trace_path = NULL;
char pathname[PATH_MAX];
ua_sess = lookup_session_by_app(usess, app);
PERROR("snprintf snapshot path");
goto error;
}
+ /* Free path allowed on previous iteration. */
+ free(trace_path);
trace_path = setup_channel_trace_path(usess->consumer, pathname);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
case LTTNG_OK:
break;
case LTTNG_ERR_CHAN_NOT_FOUND:
- free(trace_path);
continue;
default:
- free(trace_path);
goto error;
}
}
ua_sess->effective_credentials.uid,
ua_sess->effective_credentials.gid,
trace_path, wait, 0);
- free(trace_path);
switch (status) {
case LTTNG_OK:
break;
}
error:
+ free(trace_path);
rcu_read_unlock();
return status;
}
{
struct ust_app *app;
+ /*
+ * Create the toplevel ust/ directory in case no apps are running.
+ */
+ chunk_status = lttng_trace_chunk_create_subdirectory(
+ usess->current_trace_chunk,
+ DEFAULT_UST_TRACE_DIR);
+ if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+ ret = LTTNG_ERR_CREATE_DIR_FAIL;
+ goto error;
+ }
+
cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app,
pid_n.node) {
struct ust_app_session *ua_sess;