#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"
case LTTNG_BUFFER_PER_UID:
{
struct buffer_reg_uid *reg_uid = buffer_reg_uid_find(
- ua_sess->tracing_id, ua_sess->bits_per_long, ua_sess->uid);
+ ua_sess->tracing_id, ua_sess->bits_per_long,
+ ua_sess->real_credentials.uid);
if (!reg_uid) {
goto error;
}
* 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;
}
static void shadow_copy_session(struct ust_app_session *ua_sess,
struct ltt_ust_session *usess, struct ust_app *app)
{
- time_t rawtime;
struct tm *timeinfo;
char datetime[16];
int ret;
char tmp_shm_path[PATH_MAX];
- /* Get date and time for unique app path */
- time(&rawtime);
- timeinfo = localtime(&rawtime);
+ timeinfo = localtime(&app->registration_time);
strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo);
DBG2("Shadow copy of session handle %d", ua_sess->handle);
ua_sess->tracing_id = usess->id;
ua_sess->id = get_next_session_id();
- ua_sess->uid = app->uid;
- ua_sess->gid = app->gid;
- ua_sess->euid = usess->uid;
- ua_sess->egid = usess->gid;
+ ua_sess->real_credentials.uid = app->uid;
+ ua_sess->real_credentials.gid = app->gid;
+ ua_sess->effective_credentials.uid = usess->uid;
+ ua_sess->effective_credentials.gid = usess->gid;
ua_sess->buffer_type = usess->buffer_type;
ua_sess->bits_per_long = app->bits_per_long;
break;
case LTTNG_BUFFER_PER_UID:
ret = snprintf(ua_sess->path, sizeof(ua_sess->path),
- DEFAULT_UST_TRACE_UID_PATH, ua_sess->uid, app->bits_per_long);
+ DEFAULT_UST_TRACE_UID_PATH,
+ ua_sess->real_credentials.uid,
+ app->bits_per_long);
break;
default:
assert(0);
switch (ua_sess->buffer_type) {
case LTTNG_BUFFER_PER_PID:
ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path),
- DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s",
+ "/" DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s",
app->name, app->pid, datetime);
break;
case LTTNG_BUFFER_PER_UID:
ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path),
- DEFAULT_UST_TRACE_UID_PATH,
+ "/" DEFAULT_UST_TRACE_UID_PATH,
app->uid, app->bits_per_long);
break;
default:
app->bits_per_long, app->uint8_t_alignment,
app->uint16_t_alignment, app->uint32_t_alignment,
app->uint64_t_alignment, app->long_alignment,
- app->byte_order, app->version.major,
- app->version.minor, reg_pid->root_shm_path,
- reg_pid->shm_path,
- ua_sess->euid, ua_sess->egid);
+ 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->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
notification_ret = notification_thread_command_add_channel(
notification_thread_handle, session->name,
- ua_sess->euid, ua_sess->egid,
- ua_chan->name,
- ua_chan->key,
- LTTNG_DOMAIN_UST,
+ ua_sess->effective_credentials.uid,
+ ua_sess->effective_credentials.gid, ua_chan->name,
+ ua_chan->key, LTTNG_DOMAIN_UST,
ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
if (notification_ret != LTTNG_OK) {
ret = - (int) notification_ret;
cmd_ret = notification_thread_command_add_channel(
notification_thread_handle, session->name,
- ua_sess->euid, ua_sess->egid,
- ua_chan->name,
- ua_chan->key,
- LTTNG_DOMAIN_UST,
+ ua_sess->effective_credentials.uid,
+ ua_sess->effective_credentials.gid, ua_chan->name,
+ ua_chan->key, LTTNG_DOMAIN_UST,
ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
if (cmd_ret != LTTNG_OK) {
ret = - (int) cmd_ret;
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;
}
assert(app);
assert(app->notify_sock >= 0);
+ app->registration_time = time(NULL);
+
rcu_read_lock();
/*
if (session_was_created) {
destroy_app_session(app, ua_sess);
}
- goto error_rcu_unlock;
+ /* Continue to the next application. */
}
}
health_code_update();
skip_setup:
- /* This start the UST tracing */
+ /* This starts the UST tracing */
pthread_mutex_lock(&app->sock_lock);
ret = ustctl_start_session(app->sock, ua_sess->handle);
pthread_mutex_unlock(&app->sock_lock);
*/
enum lttng_error_code ust_app_snapshot_record(
const struct ltt_ust_session *usess,
- const struct snapshot_output *output, int wait,
+ const struct consumer_output *output, int wait,
uint64_t nb_packets_per_stream)
{
int ret = 0;
enum lttng_error_code status = LTTNG_OK;
struct lttng_ht_iter iter;
struct ust_app *app;
- char pathname[PATH_MAX];
+ 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 pathname[PATH_MAX];
+ size_t consumer_path_offset = 0;
if (!reg->registry->reg.ust->metadata_key) {
/* Skip since no metadata is present */
}
memset(pathname, 0, sizeof(pathname));
- /*
- * DEFAULT_UST_TRACE_UID_PATH already contains a path
- * separator.
- */
ret = snprintf(pathname, sizeof(pathname),
- DEFAULT_UST_TRACE_DIR DEFAULT_UST_TRACE_UID_PATH,
+ DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH,
reg->uid, reg->bits_per_long);
if (ret < 0) {
PERROR("snprintf snapshot path");
status = LTTNG_ERR_INVALID;
goto error;
}
-
+ /* Free path allowed on previous iteration. */
+ free(trace_path);
+ trace_path = setup_channel_trace_path(usess->consumer, pathname,
+ &consumer_path_offset);
+ if (!trace_path) {
+ status = LTTNG_ERR_INVALID;
+ goto error;
+ }
/* Add the UST default trace dir to path. */
cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
reg_chan, node.node) {
status = consumer_snapshot_channel(socket,
reg_chan->consumer_key,
output, 0, usess->uid,
- usess->gid, pathname, wait,
+ usess->gid, &trace_path[consumer_path_offset], wait,
nb_packets_per_stream);
if (status != LTTNG_OK) {
goto error;
}
status = consumer_snapshot_channel(socket,
reg->registry->reg.ust->metadata_key, output, 1,
- usess->uid, usess->gid, pathname, wait, 0);
+ usess->uid, usess->gid, &trace_path[consumer_path_offset],
+ wait, 0);
if (status != LTTNG_OK) {
goto error;
}
struct ust_app_channel *ua_chan;
struct ust_app_session *ua_sess;
struct ust_registry_session *registry;
+ char pathname[PATH_MAX];
+ size_t consumer_path_offset = 0;
ua_sess = lookup_session_by_app(usess, app);
if (!ua_sess) {
/* Get the right consumer socket for the application. */
socket = consumer_find_socket_by_bitness(app->bits_per_long,
- output->consumer);
+ output);
if (!socket) {
status = LTTNG_ERR_INVALID;
goto error;
/* Add the UST default trace dir to path. */
memset(pathname, 0, sizeof(pathname));
- ret = snprintf(pathname, sizeof(pathname), DEFAULT_UST_TRACE_DIR "%s",
+ ret = snprintf(pathname, sizeof(pathname), DEFAULT_UST_TRACE_DIR "/%s",
ua_sess->path);
if (ret < 0) {
status = LTTNG_ERR_INVALID;
PERROR("snprintf snapshot path");
goto error;
}
-
+ /* Free path allowed on previous iteration. */
+ free(trace_path);
+ trace_path = setup_channel_trace_path(usess->consumer, pathname,
+ &consumer_path_offset);
+ if (!trace_path) {
+ status = LTTNG_ERR_INVALID;
+ goto error;
+ }
cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
ua_chan, node.node) {
status = consumer_snapshot_channel(socket,
- ua_chan->key, output,
- 0, ua_sess->euid, ua_sess->egid,
- pathname, wait,
+ ua_chan->key, output, 0,
+ ua_sess->effective_credentials
+ .uid,
+ ua_sess->effective_credentials
+ .gid,
+ &trace_path[consumer_path_offset], wait,
nb_packets_per_stream);
switch (status) {
case LTTNG_OK:
continue;
}
status = consumer_snapshot_channel(socket,
- registry->metadata_key, output,
- 1, ua_sess->euid, ua_sess->egid,
- pathname, wait, 0);
+ registry->metadata_key, output, 1,
+ ua_sess->effective_credentials.uid,
+ ua_sess->effective_credentials.gid,
+ &trace_path[consumer_path_offset], wait, 0);
switch (status) {
case LTTNG_OK:
break;
}
error:
+ free(trace_path);
rcu_read_unlock();
return status;
}
/* Rotate the data channels. */
cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
ua_chan, node.node) {
- ret = consumer_rotate_channel(socket, ua_chan->key,
- ua_sess->euid, ua_sess->egid,
+ ret = consumer_rotate_channel(socket,
+ ua_chan->key,
+ ua_sess->effective_credentials
+ .uid,
+ ua_sess->effective_credentials
+ .gid,
ua_sess->consumer,
/* is_metadata_channel */ false);
if (ret < 0) {
/* Rotate the metadata channel. */
(void) push_metadata(registry, usess->consumer);
- ret = consumer_rotate_channel(socket, registry->metadata_key,
- ua_sess->euid, ua_sess->egid,
+ ret = consumer_rotate_channel(socket,
+ registry->metadata_key,
+ ua_sess->effective_credentials.uid,
+ ua_sess->effective_credentials.gid,
ua_sess->consumer,
/* is_metadata_channel */ true);
if (ret < 0) {
cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
fmt_ret = asprintf(&pathname_index,
- DEFAULT_UST_TRACE_DIR DEFAULT_UST_TRACE_UID_PATH "/" DEFAULT_INDEX_DIR,
+ DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH "/" DEFAULT_INDEX_DIR,
reg->uid, reg->bits_per_long);
if (fmt_ret < 0) {
ERR("Failed to format channel index directory");
{
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;
}
fmt_ret = asprintf(&pathname_index,
- DEFAULT_UST_TRACE_DIR "%s/" DEFAULT_INDEX_DIR,
+ DEFAULT_UST_TRACE_DIR "/%s/" DEFAULT_INDEX_DIR,
ua_sess->path);
if (fmt_ret < 0) {
ERR("Failed to format channel index directory");