lttng::utils::container_of(head, &ust_app_session::rcu_head);
lttng_ht_destroy(ua_sess->channels);
- free(ua_sess);
+ delete ua_sess;
}
/*
LTTNG_ASSERT(ua_sess);
ASSERT_RCU_READ_LOCKED();
- pthread_mutex_lock(&ua_sess->lock);
+ /* Locked for the duration of the function. */
+ auto locked_ua_sess = ua_sess->lock();
LTTNG_ASSERT(!ua_sess->deleted);
ua_sess->deleted = true;
LTTNG_ASSERT(!ret);
}
- pthread_mutex_unlock(&ua_sess->lock);
-
consumer_output_put(ua_sess->consumer);
-
call_rcu(&ua_sess->rcu_head, delete_ust_app_session_rcu);
}
struct ust_app_session *ua_sess;
/* Init most of the default value by allocating and zeroing */
- ua_sess = zmalloc<ust_app_session>();
+ ua_sess = new ust_app_session;
if (ua_sess == nullptr) {
PERROR("malloc");
goto error_free;
ua_sess->handle = -1;
ua_sess->channels = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
ua_sess->metadata_attr.type = LTTNG_UST_ABI_CHAN_METADATA;
- pthread_mutex_init(&ua_sess->lock, nullptr);
return ua_sess;
* Add session to list for teardown. This is safe since at this point we
* are the only one using this list.
*/
- lttng::pthread::lock_guard ust_app_session_lock(ua_sess->lock);
+ auto locked_ua_sess = ua_sess->lock();
if (ua_sess->deleted) {
continue;
struct ust_app_channel *ua_chan = nullptr;
LTTNG_ASSERT(ua_sess);
- ASSERT_LOCKED(ua_sess->lock);
if (!strncmp(uchan->name, DEFAULT_METADATA_NAME, sizeof(uchan->name))) {
copy_channel_attr_to_ustctl(&ua_sess->metadata_attr, &uchan->attr);
continue;
}
- pthread_mutex_lock(&ua_sess->lock);
-
+ auto locked_ua_sess = ua_sess->lock();
if (ua_sess->deleted) {
- pthread_mutex_unlock(&ua_sess->lock);
continue;
}
* an application exit.
*/
if (!ua_chan_node) {
- pthread_mutex_unlock(&ua_sess->lock);
continue;
}
"Skipping app",
uevent->attr.name,
app->pid);
- goto next_app;
+ continue;
}
ret = enable_ust_app_event(ua_event, app);
if (ret < 0) {
- pthread_mutex_unlock(&ua_sess->lock);
goto error;
}
- next_app:
- pthread_mutex_unlock(&ua_sess->lock);
}
}
error:
continue;
}
- pthread_mutex_lock(&ua_sess->lock);
+ auto locked_ua_sess = ua_sess->lock();
- if (ua_sess->deleted) {
- pthread_mutex_unlock(&ua_sess->lock);
+ if (locked_ua_sess->deleted) {
continue;
}
ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node);
ret = create_ust_app_event(ua_chan, uevent, app);
- pthread_mutex_unlock(&ua_sess->lock);
if (ret < 0) {
if (ret != -LTTNG_UST_ERR_EXIST) {
/* Possible value at this point: -ENOMEM. If so, we stop! */
DBG("Starting tracing for ust app pid %d", app->pid);
lttng::urcu::read_lock_guard read_lock;
+ const auto update_health_code_on_exit =
+ lttng::make_scope_exit([]() noexcept { health_code_update(); });
if (!app->compatible) {
- goto end;
+ return 0;
}
ua_sess = lookup_session_by_app(usess, app);
if (ua_sess == nullptr) {
/* The session is in teardown process. Ignore and continue. */
- goto end;
+ return 0;
}
- pthread_mutex_lock(&ua_sess->lock);
+ auto locked_ua_sess = ua_sess->lock();
- if (ua_sess->deleted) {
- pthread_mutex_unlock(&ua_sess->lock);
- goto end;
- }
-
- if (ua_sess->enabled) {
- pthread_mutex_unlock(&ua_sess->lock);
- goto end;
+ if (locked_ua_sess->deleted) {
+ return 0;
}
- /* Upon restart, we skip the setup, already done */
- if (ua_sess->started) {
- goto skip_setup;
+ if (locked_ua_sess->enabled) {
+ return 0;
}
- health_code_update();
-
-skip_setup:
/* This starts the UST tracing */
pthread_mutex_lock(&app->sock_lock);
ret = lttng_ust_ctl_start_session(app->sock, ua_sess->handle);
DBG3("UST app start session failed. Application is dead: pid = %d, sock = %d",
app->pid,
app->sock);
- pthread_mutex_unlock(&ua_sess->lock);
- goto end;
+ return 0;
} else if (ret == -EAGAIN) {
WARN("UST app start session failed. Communication time out: pid = %d, sock = %d",
app->pid,
app->sock);
- pthread_mutex_unlock(&ua_sess->lock);
- goto end;
+ return 0;
} else {
ERR("UST app start session failed with ret %d: pid = %d, sock = %d",
app->pid,
app->sock);
}
- goto error_unlock;
+
+ return -1;
}
/* Indicate that the session has been started once */
ua_sess->started = true;
ua_sess->enabled = true;
- pthread_mutex_unlock(&ua_sess->lock);
-
health_code_update();
/* Quiescent wait after starting trace */
}
}
-end:
- health_code_update();
return 0;
-
-error_unlock:
- pthread_mutex_unlock(&ua_sess->lock);
- health_code_update();
- return -1;
}
/*
DBG("Stopping tracing for ust app pid %d", app->pid);
lttng::urcu::read_lock_guard read_lock;
+ const auto update_health_code_on_exit =
+ lttng::make_scope_exit([]() noexcept { health_code_update(); });
if (!app->compatible) {
- goto end_no_session;
+ return 0;
}
ua_sess = lookup_session_by_app(usess, app);
if (ua_sess == nullptr) {
- goto end_no_session;
+ return 0;
}
- pthread_mutex_lock(&ua_sess->lock);
+ auto locked_ua_sess = ua_sess->lock();
if (ua_sess->deleted) {
- pthread_mutex_unlock(&ua_sess->lock);
- goto end_no_session;
+ return 0;
}
/*
* indicate that this is a stop error.
*/
if (!ua_sess->started) {
- goto error_rcu_unlock;
+ return -1;
}
health_code_update();
DBG3("UST app stop session failed. Application is dead: pid = %d, sock = %d",
app->pid,
app->sock);
- goto end_unlock;
+ return 0;
} else if (ret == -EAGAIN) {
WARN("UST app stop session failed. Communication time out: pid = %d, sock = %d",
app->pid,
app->sock);
- goto end_unlock;
+ return 0;
} else {
ERR("UST app stop session failed with ret %d: pid = %d, sock = %d",
app->pid,
app->sock);
}
- goto error_rcu_unlock;
+
+ return -1;
}
health_code_update();
(void) push_metadata(locked_registry, ua_sess->consumer);
}
-end_unlock:
- pthread_mutex_unlock(&ua_sess->lock);
-end_no_session:
- health_code_update();
return 0;
-
-error_rcu_unlock:
- pthread_mutex_unlock(&ua_sess->lock);
- health_code_update();
- return -1;
}
static int ust_app_flush_app_session(ust_app& app, ust_app_session& ua_sess)
struct ust_app_channel *ua_chan;
struct consumer_socket *socket;
+ const auto update_health_code_on_exit =
+ lttng::make_scope_exit([]() noexcept { health_code_update(); });
+
DBG("Flushing app session buffers for ust app pid %d", app.pid);
if (!app.compatible) {
- goto end_not_compatible;
+ return 0;
}
- pthread_mutex_lock(&ua_sess.lock);
-
- if (ua_sess.deleted) {
- goto end_deleted;
+ const auto locked_ua_sess = ua_sess.lock();
+ if (locked_ua_sess->deleted) {
+ return 0;
}
health_code_update();
break;
}
- health_code_update();
-
-end_deleted:
- pthread_mutex_unlock(&ua_sess.lock);
-
-end_not_compatible:
- health_code_update();
return retval;
}
DBG("Clearing stream quiescent state for ust app pid %d", app->pid);
lttng::urcu::read_lock_guard read_lock;
+ const auto update_health_code_on_exit =
+ lttng::make_scope_exit([]() noexcept { health_code_update(); });
if (!app->compatible) {
- goto end_not_compatible;
+ return 0;
}
- pthread_mutex_lock(&ua_sess->lock);
-
- if (ua_sess->deleted) {
- goto end_unlock;
+ const auto locked_ua_sess = ua_sess->lock();
+ if (locked_ua_sess->deleted) {
+ return 0;
}
health_code_update();
socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, ua_sess->consumer);
if (!socket) {
ERR("Failed to find consumer (%" PRIu32 ") socket", app->abi.bits_per_long);
- ret = -1;
- goto end_unlock;
+ return -1;
}
/* Clear quiescent state. */
break;
}
- health_code_update();
-
-end_unlock:
- pthread_mutex_unlock(&ua_sess->lock);
-
-end_not_compatible:
- health_code_update();
return ret;
}
ret = find_or_create_ust_app_session(usess, app, &ua_sess, nullptr);
if (ret < 0) {
/* Tracer is probably gone or ENOMEM. */
- goto end;
+ return;
}
LTTNG_ASSERT(ua_sess);
- pthread_mutex_lock(&ua_sess->lock);
- if (ua_sess->deleted) {
- goto deleted_session;
+ const auto locked_ua_sess = ua_sess->lock();
+ if (locked_ua_sess->deleted) {
+ return;
}
{
usess->id);
}
}
-
-deleted_session:
- pthread_mutex_unlock(&ua_sess->lock);
-end:
- return;
}
static void ust_app_global_destroy(struct ltt_ust_session *usess, struct ust_app *app)
continue;
}
- pthread_mutex_lock(&ua_sess->lock);
-
- if (ua_sess->deleted) {
- pthread_mutex_unlock(&ua_sess->lock);
+ const auto locked_ua_sess = ua_sess->lock();
+ if (locked_ua_sess->deleted) {
continue;
}
lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter);
ua_chan_node = lttng_ht_iter_get_node<lttng_ht_node_str>(&uiter);
if (ua_chan_node == nullptr) {
- goto next_app;
+ continue;
}
ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
ret = create_ust_app_channel_context(ua_chan, &uctx->ctx, app);
if (ret < 0) {
- goto next_app;
+ continue;
}
- next_app:
- pthread_mutex_unlock(&ua_sess->lock);
}
}
DBG("Regenerating the metadata for ust app pid %d", app->pid);
lttng::urcu::read_lock_guard read_lock;
+ const auto update_health_code_on_exit =
+ lttng::make_scope_exit([]() noexcept { health_code_update(); });
ua_sess = lookup_session_by_app(usess, app);
if (ua_sess == nullptr) {
/* The session is in teardown process. Ignore and continue. */
- goto end;
+ return 0;
}
- pthread_mutex_lock(&ua_sess->lock);
-
- if (ua_sess->deleted) {
- goto end_unlock;
+ const auto locked_ua_sess = ua_sess->lock();
+ if (locked_ua_sess->deleted) {
+ return 0;
}
pthread_mutex_lock(&app->sock_lock);
ret = lttng_ust_ctl_regenerate_statedump(app->sock, ua_sess->handle);
pthread_mutex_unlock(&app->sock_lock);
-
-end_unlock:
- pthread_mutex_unlock(&ua_sess->lock);
-
-end:
- health_code_update();
return ret;
}
urcu_ref_put(&app->ref, ust_app_release);
}
+
+ust_app_session::const_locked_weak_ref ust_app_session::lock() const noexcept
+{
+ pthread_mutex_lock(&_lock);
+ return ust_app_session::const_locked_weak_ref(*this);
+}
+
+ust_app_session::locked_weak_ref ust_app_session::lock() noexcept
+{
+ pthread_mutex_lock(&_lock);
+ return ust_app_session::locked_weak_ref(*this);
+}
+
+void ust_app_session::_const_session_unlock(const ust_app_session *session)
+{
+ pthread_mutex_unlock(&session->_lock);
+}
+
+void ust_app_session::_session_unlock(ust_app_session *session)
+{
+ pthread_mutex_unlock(&session->_lock);
+}
#include <common/format.hpp>
#include <common/index-allocator.hpp>
+#include <common/scope-exit.hpp>
#include <common/uuid.hpp>
#include <stdint.h>
};
struct ust_app_session {
- /*
- * Lock protecting this session's ust app interaction. Held
- * across command send/recv to/from app. Never nests within the
- * session registry lock.
- */
- pthread_mutex_t lock;
-
- bool enabled;
+private:
+ static void _session_unlock(ust_app_session *session);
+ static void _const_session_unlock(const ust_app_session *session);
+
+public:
+ using locked_weak_ref = lttng::non_copyable_reference<
+ ust_app_session,
+ lttng::memory::create_deleter_class<ust_app_session,
+ ust_app_session::_session_unlock>::deleter>;
+ using const_locked_weak_ref = lttng::non_copyable_reference<
+ const ust_app_session,
+ lttng::memory::create_deleter_class<const ust_app_session,
+ ust_app_session::_const_session_unlock>::deleter>;
+
+ ust_app_session::const_locked_weak_ref lock() const noexcept;
+ ust_app_session::locked_weak_ref lock() noexcept;
+
+ bool enabled = false;
/* started: has the session been in started state at any time ? */
- bool started; /* allows detection of start vs restart. */
- int handle; /* used has unique identifier for app session */
+ bool started = false; /* allows detection of start vs restart. */
+ int handle = 0; /* used has unique identifier for app session */
- bool deleted; /* Session deleted flag. Check with lock held. */
+ bool deleted = false; /* Session deleted flag. Check with lock held. */
/*
* Tracing session ID. Multiple ust app session can have the same tracing
* session id making this value NOT unique to the object.
*/
- uint64_t tracing_id;
- uint64_t id; /* Unique session identifier */
- struct lttng_ht *channels; /* Registered channels */
- struct lttng_ht_node_u64 node;
+ uint64_t tracing_id = 0;
+ uint64_t id = 0; /* Unique session identifier */
+ struct lttng_ht *channels = nullptr; /* Registered channels */
+ struct lttng_ht_node_u64 node = {};
/*
* Node indexed by UST session object descriptor (handle). Stored in the
* ust_sessions_objd hash table in the ust_app object.
*/
- struct lttng_ht_node_ulong ust_objd_node;
+ struct lttng_ht_node_ulong ust_objd_node = {};
/* Starts with 'ust'; no leading slash. */
- char path[PATH_MAX];
+ char path[PATH_MAX] = {};
/* UID/GID of the application owning the session */
- struct lttng_credentials real_credentials;
+ struct lttng_credentials real_credentials = {};
/* Effective UID and GID. Same as the tracing session. */
- struct lttng_credentials effective_credentials;
- struct cds_list_head teardown_node;
+ struct lttng_credentials effective_credentials = {};
+ struct cds_list_head teardown_node = {};
/*
* Once at least *one* session is created onto the application, the
* corresponding consumer is set so we can use it on unregistration.
*/
- struct consumer_output *consumer;
- enum lttng_buffer_type buffer_type;
+ struct consumer_output *consumer = nullptr;
+ enum lttng_buffer_type buffer_type = LTTNG_BUFFER_PER_PID;
/* ABI of the session. Same value as the application. */
- uint32_t bits_per_long;
+ uint32_t bits_per_long = 0;
/* For delayed reclaim */
- struct rcu_head rcu_head;
+ struct rcu_head rcu_head = {};
/* If the channel's streams have to be outputed or not. */
- unsigned int output_traces;
- unsigned int live_timer_interval; /* usec */
+ unsigned int output_traces = 0;
+ unsigned int live_timer_interval = 0; /* usec */
/* Metadata channel attributes. */
- struct lttng_ust_ctl_consumer_channel_attr metadata_attr;
+ struct lttng_ust_ctl_consumer_channel_attr metadata_attr = {};
- char root_shm_path[PATH_MAX];
- char shm_path[PATH_MAX];
+ char root_shm_path[PATH_MAX] = {};
+ char shm_path[PATH_MAX] = {};
+
+private:
+ /*
+ * Lock protecting this session's ust app interaction. Held
+ * across command send/recv to/from app. Never nests within the
+ * session registry lock.
+ */
+ mutable pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
};
/*