/*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 EfficiOS Inc.
*
* SPDX-License-Identifier: GPL-2.0-only
*
#include <sys/types.h>
#include <pthread.h>
-#include <common/common.h>
-#include <common/utils.h>
-#include <common/trace-chunk.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-#include <lttng/location-internal.h>
-#include "lttng-sessiond.h"
-#include "kernel.h"
+#include <common/common.hpp>
+#include <common/utils.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <lttng/location-internal.hpp>
+#include "lttng-sessiond.hpp"
+#include "kernel.hpp"
-#include "session.h"
-#include "utils.h"
-#include "trace-ust.h"
-#include "timer.h"
-#include "cmd.h"
+#include "session.hpp"
+#include "utils.hpp"
+#include "trace-ust.hpp"
+#include "timer.hpp"
+#include "cmd.hpp"
struct ltt_session_destroy_notifier_element {
ltt_session_destroy_notifier notifier;
static void ltt_sessions_ht_destroy(void)
{
if (ltt_sessions_ht_by_id) {
- ht_cleanup_push(ltt_sessions_ht_by_id);
+ lttng_ht_destroy(ltt_sessions_ht_by_id);
ltt_sessions_ht_by_id = NULL;
}
if (ltt_sessions_ht_by_name) {
- ht_cleanup_push(ltt_sessions_ht_by_name);
+ lttng_ht_destroy(ltt_sessions_ht_by_name);
ltt_sessions_ht_by_name = NULL;
}
/*
* Test if ltt_sessions_ht_by_id/name are empty.
- * Return 1 if empty, 0 if not empty.
+ * Return `false` if hash table objects are null.
* The session list lock must be held.
*/
-static int ltt_sessions_ht_empty(void)
+static bool ltt_sessions_ht_empty(void)
{
- unsigned long count;
+ bool empty = false;
if (!ltt_sessions_ht_by_id) {
- count = 0;
+ /* The hash tables do not exist yet. */
goto end;
}
LTTNG_ASSERT(ltt_sessions_ht_by_name);
- count = lttng_ht_get_count(ltt_sessions_ht_by_id);
- LTTNG_ASSERT(count == lttng_ht_get_count(ltt_sessions_ht_by_name));
+ if (lttng_ht_get_count(ltt_sessions_ht_by_id) == 0) {
+ /* Not empty.*/
+ goto end;
+ }
+
+ /*
+ * At this point it is expected that the `ltt_sessions_ht_by_name` ht is
+ * empty.
+ *
+ * The removal from both hash tables is done in two different
+ * places:
+ * - removal from `ltt_sessions_ht_by_name` is done during
+ * `session_destroy()`
+ * - removal from `ltt_sessions_ht_by_id` is done later
+ * in `session_release()` on the last reference put.
+ *
+ * This means that it is possible for `ltt_sessions_ht_by_name` to be
+ * empty but for `ltt_sessions_ht_by_id` to still contain objects when
+ * multiple sessions exists. The reverse is false, hence this sanity
+ * check.
+ */
+ LTTNG_ASSERT(lttng_ht_get_count(ltt_sessions_ht_by_name) == 0);
+ empty = true;
end:
- return count ? 0 : 1;
+ return empty;
}
/*
- * Remove a ltt_session from the ltt_sessions_ht_by_id/name.
+ * Remove a ltt_session from the ltt_sessions_ht_by_id.
* If empty, the ltt_sessions_ht_by_id/name HTs are freed.
* The session list lock must be held.
*/
ret = lttng_ht_del(ltt_sessions_ht_by_id, &iter);
LTTNG_ASSERT(!ret);
- iter.iter.node = &ls->node_by_name.node;
- ret = lttng_ht_del(ltt_sessions_ht_by_name, &iter);
- LTTNG_ASSERT(!ret);
-
if (ltt_sessions_ht_empty()) {
DBG("Empty ltt_sessions_ht_by_id/name, destroying hast tables");
ltt_sessions_ht_destroy();
*/
void session_destroy(struct ltt_session *session)
{
+ int ret;
+ struct lttng_ht_iter iter;
+
LTTNG_ASSERT(!session->destroyed);
session->destroyed = true;
+
+ /*
+ * Remove immediately from the "session by name" hash table. Only one
+ * session is expected to exist with a given name for at any given time.
+ *
+ * Even if a session still technically exists for a little while longer,
+ * there is no point in performing action on a "destroyed" session.
+ */
+ iter.iter.node = &session->node_by_name.node;
+ ret = lttng_ht_del(ltt_sessions_ht_by_name, &iter);
+ LTTNG_ASSERT(!ret);
+
session_put(session);
}
struct lttng_ht_iter iter;
struct ltt_session *ls;
+ ASSERT_RCU_READ_LOCKED();
ASSERT_LOCKED(ltt_session_list.lock);
if (!ltt_sessions_ht_by_id) {
goto error;
}
}
- new_session = (ltt_session *) zmalloc(sizeof(struct ltt_session));
+ new_session = zmalloc<ltt_session>();
if (!new_session) {
PERROR("Failed to allocate an ltt_session structure");
ret_code = LTTNG_ERR_NOMEM;