#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"
* 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;
}
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:
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");
}
/* Free path allowed on previous iteration. */
free(trace_path);
- trace_path = setup_channel_trace_path(usess->consumer, pathname);
+ trace_path = setup_channel_trace_path(usess->consumer, pathname,
+ &consumer_path_offset);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
goto error;
status = consumer_snapshot_channel(socket,
reg_chan->consumer_key,
output, 0, usess->uid,
- usess->gid, trace_path, 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, trace_path, wait, 0);
+ usess->uid, usess->gid, &trace_path[consumer_path_offset],
+ wait, 0);
if (status != LTTNG_OK) {
goto error;
}
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) {
/* 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;
}
/* Free path allowed on previous iteration. */
free(trace_path);
- trace_path = setup_channel_trace_path(usess->consumer, pathname);
+ trace_path = setup_channel_trace_path(usess->consumer, pathname,
+ &consumer_path_offset);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
goto error;
.uid,
ua_sess->effective_credentials
.gid,
- trace_path, wait,
+ &trace_path[consumer_path_offset], wait,
nb_packets_per_stream);
switch (status) {
case LTTNG_OK:
registry->metadata_key, output, 1,
ua_sess->effective_credentials.uid,
ua_sess->effective_credentials.gid,
- trace_path, wait, 0);
+ &trace_path[consumer_path_offset], wait, 0);
switch (status) {
case LTTNG_OK:
break;
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");