session_lock_list();
cds_list_for_each_entry_safe(session, stmp, &list->head, list) {
+ if (!session_get(session)) {
+ continue;
+ }
+
session_lock(session);
if (session->ust_session) {
struct agent *agt;
rcu_read_unlock();
}
session_unlock(session);
+ session_put(session);
}
session_unlock_list();
}
size_t nb_uri, lttng_sock_cred *creds, unsigned int live_timer)
{
int ret;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
assert(name);
assert(creds);
- /*
- * Verify if the session already exist
- *
- * XXX: There is no need for the session lock list here since the caller
- * (process_client_msg) is holding it. We might want to change that so a
- * single command does not lock the entire session list.
- */
+ /* Check if the session already exists. */
+ session_lock_list();
session = session_find_by_name(name);
+ session_unlock_list();
if (session != NULL) {
ret = LTTNG_ERR_EXIST_SESS;
- goto find_error;
+ goto end;
}
/* Create tracing session in the registry */
ret = session_create(name, LTTNG_SOCK_GET_UID_CRED(creds),
LTTNG_SOCK_GET_GID_CRED(creds));
if (ret != LTTNG_OK) {
- goto session_error;
+ goto end;
}
- /*
- * Get the newly created session pointer back
- *
- * XXX: There is no need for the session lock list here since the caller
- * (process_client_msg) is holding it. We might want to change that so a
- * single command does not lock the entire session list.
- */
+ /* Get the newly created session pointer back. */
+ session_lock_list();
session = session_find_by_name(name);
+ session_unlock_list();
assert(session);
session->live_timer = live_timer;
session->consumer = consumer_create_output(CONSUMER_DST_LOCAL);
if (session->consumer == NULL) {
ret = LTTNG_ERR_FATAL;
- goto consumer_error;
+ goto end;
}
if (uris) {
ret = cmd_set_consumer_uri(session, nb_uri, uris);
if (ret != LTTNG_OK) {
- goto consumer_error;
+ goto end;
}
session->output_traces = 1;
} else {
session->consumer->enabled = 1;
- return LTTNG_OK;
-
-consumer_error:
- session_destroy(session);
-session_error:
-find_error:
+ ret = LTTNG_OK;
+end:
+ if (session) {
+ session_lock_list();
+ session_put(session);
+ session_unlock_list();
+ }
return ret;
}
size_t nb_uri, lttng_sock_cred *creds)
{
int ret;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
struct snapshot_output *new_output = NULL;
assert(name);
*/
ret = cmd_create_session_uri(name, NULL, 0, creds, 0);
if (ret != LTTNG_OK) {
- goto error;
+ goto end;
}
/* Get the newly created session pointer back. This should NEVER fail. */
+ session_lock_list();
session = session_find_by_name(name);
+ session_unlock_list();
assert(session);
/* Flag session for snapshot mode. */
/* Skip snapshot output creation if no URI is given. */
if (nb_uri == 0) {
+ /* Not an error. */
goto end;
}
snapshot_add_output(&session->snapshot, new_output);
rcu_read_unlock();
-end:
- return LTTNG_OK;
+ ret = LTTNG_OK;
+ goto end;
error_snapshot:
snapshot_output_destroy(new_output);
error_snapshot_alloc:
- session_destroy(session);
-error:
+end:
+ if (session) {
+ session_lock_list();
+ session_put(session);
+ session_unlock_list();
+ }
return ret;
}
*
* Called with session lock held.
*/
-int cmd_destroy_session(struct ltt_session *session, int wpipe,
+int cmd_destroy_session(struct ltt_session *session,
struct notification_thread_handle *notification_thread_handle)
{
int ret;
- struct ltt_ust_session *usess;
- struct ltt_kernel_session *ksess;
/* Safety net */
assert(session);
- usess = session->ust_session;
- ksess = session->kernel_session;
-
DBG("Begin destroy session %s (id %" PRIu64 ")", session->name, session->id);
if (session->rotation_pending_check_timer_enabled) {
rename_active_chunk(session);
}
- /* Clean kernel session teardown */
- kernel_destroy_session(ksess);
-
- /* UST session teardown */
- if (usess) {
- /* Close any relayd session */
- consumer_output_send_destroy_relayd(usess->consumer);
-
- /* Destroy every UST application related to this session. */
- ret = ust_app_destroy_trace_all(usess);
- if (ret) {
- ERR("Error in ust_app_destroy_trace_all");
- }
-
- /* Clean up the rest. */
- trace_ust_destroy_session(usess);
- }
-
- /*
- * Must notify the kernel thread here to update it's poll set in order to
- * remove the channel(s)' fd just destroyed.
- */
- ret = notify_thread_pipe(wpipe);
- if (ret < 0) {
- PERROR("write kernel poll pipe");
- }
-
if (session->shm_path[0]) {
/*
* When a session is created with an explicit shm_path,
sizeof(destroy_completion_handler.shm_path));
assert(!ret);
}
- ret = session_destroy(session);
+
+ /*
+ * The session is destroyed. However, note that the command context
+ * still holds a reference to the session, thus delaying its destruction
+ * _at least_ up to the point when that reference is released.
+ */
+ session_destroy(session);
+ ret = LTTNG_OK;
return ret;
}
* the buffer.
*/
cds_list_for_each_entry(session, &list->head, list) {
+ if (!session_get(session)) {
+ continue;
+ }
/*
* Only list the sessions the user can control.
*/
- if (!session_access_ok(session, uid, gid)) {
+ if (!session_access_ok(session, uid, gid) ||
+ session->destroyed) {
+ session_put(session);
continue;
}
}
if (ret < 0) {
PERROR("snprintf session path");
+ session_put(session);
continue;
}
sessions[i].snapshot_mode = session->snapshot_mode;
sessions[i].live_timer_interval = session->live_timer;
i++;
+ session_put(session);
}
}
size_t nb_uri, lttng_sock_cred *creds, unsigned int live_timer);
int cmd_create_session_snapshot(char *name, struct lttng_uri *uris,
size_t nb_uri, lttng_sock_cred *creds);
-int cmd_destroy_session(struct ltt_session *session, int wpipe,
+int cmd_destroy_session(struct ltt_session *session,
struct notification_thread_handle *notification_thread_handle);
/* Channel commands */
int kernel_tracer_fd = -1;
int apps_cmd_notify_pipe[2] = { -1, -1 };
+int kernel_poll_pipe[2] = { -1, -1 };
pid_t ppid;
pid_t child_ppid;
struct lttcomm_consumer_msg lkm;
struct consumer_output *consumer;
enum lttng_error_code status;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
struct lttng_channel_extended *channel_attr_extended;
/* Safety net */
channel->published_to_notification_thread = true;
error:
+ if (session) {
+ session_put(session);
+ }
free(pathname);
return ret;
}
char *pathname;
struct lttcomm_consumer_msg lkm;
struct consumer_output *consumer;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
rcu_read_lock();
error:
rcu_read_unlock();
free(pathname);
+ if (session) {
+ session_put(session);
+ }
return ret;
}
{
int ret = LTTNG_OK;
struct ltt_kernel_stream *stream;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
/* Safety net */
assert(channel);
error:
rcu_read_unlock();
+ if (session) {
+ session_put(session);
+ }
return ret;
}
struct consumer_socket *socket;
struct lttng_ht_iter iter;
struct ltt_kernel_metadata *saved_metadata;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
uint64_t trace_archive_id;
assert(ksess);
/* Restore metadata state.*/
ksess->metadata = saved_metadata;
ksess->metadata_stream_fd = saved_metadata_fd;
-
+ if (session) {
+ session_put(session);
+ }
rcu_read_unlock();
return status;
}
*/
extern int ht_cleanup_pipe[2];
+extern int kernel_poll_pipe[2];
+
/*
* Populated when the daemon starts with the current page size of the system.
* Set in main() with the current page size.
/* Sockets and FDs */
static int client_sock = -1;
static int apps_sock = -1;
-static int kernel_poll_pipe[2] = { -1, -1 };
/*
* This pipe is used to inform the thread managing application communication
*/
static struct ust_cmd_queue ust_cmd_queue;
-/*
- * Pointer initialized before thread creation.
- *
- * This points to the tracing session list containing the session count and a
- * mutex lock. The lock MUST be taken if you iterate over the list. The lock
- * MUST NOT be taken if you call a public function in session.c.
- *
- * The lock is nested inside the structure: session_list_ptr->lock. Please use
- * session_lock_list and session_unlock_list for lock acquisition.
- */
-static struct ltt_session_list *session_list_ptr;
-
static const char *module_proc_lttng = "/proc/lttng";
/*
{
int ret;
struct ltt_session *sess, *stmp;
+ struct ltt_session_list *session_list = session_get_list();
DBG("Cleanup sessiond");
DBG("Cleaning up all sessions");
/* Destroy session list mutex */
- if (session_list_ptr != NULL) {
- pthread_mutex_destroy(&session_list_ptr->lock);
-
+ if (session_list) {
+ session_lock_list();
/* Cleanup ALL session */
cds_list_for_each_entry_safe(sess, stmp,
- &session_list_ptr->head, list) {
- cmd_destroy_session(sess, kernel_poll_pipe[1],
+ &session_list->head, list) {
+ if (sess->destroyed) {
+ continue;
+ }
+ cmd_destroy_session(sess,
notification_thread_handle);
}
+ session_unlock_list();
+ pthread_mutex_destroy(&session_list->lock);
}
wait_consumer(&kconsumer_data);
static int update_kernel_poll(struct lttng_poll_event *events)
{
int ret;
- struct ltt_session *session;
struct ltt_kernel_channel *channel;
+ struct ltt_session *session;
+ const struct ltt_session_list *session_list = session_get_list();
DBG("Updating kernel poll set");
session_lock_list();
- cds_list_for_each_entry(session, &session_list_ptr->head, list) {
+ cds_list_for_each_entry(session, &session_list->head, list) {
+ if (!session_get(session)) {
+ continue;
+ }
session_lock(session);
if (session->kernel_session == NULL) {
session_unlock(session);
+ session_put(session);
continue;
}
ret = lttng_poll_add(events, channel->fd, LPOLLIN | LPOLLRDNORM);
if (ret < 0) {
session_unlock(session);
+ session_put(session);
goto error;
}
DBG("Channel fd %d added to kernel set", channel->fd);
struct ltt_session *session;
struct ltt_kernel_session *ksess;
struct ltt_kernel_channel *channel;
+ const struct ltt_session_list *session_list = session_get_list();
DBG("Updating kernel streams for channel fd %d", fd);
session_lock_list();
- cds_list_for_each_entry(session, &session_list_ptr->head, list) {
+ cds_list_for_each_entry(session, &session_list->head, list) {
+ if (!session_get(session)) {
+ continue;
+ }
session_lock(session);
if (session->kernel_session == NULL) {
session_unlock(session);
+ session_put(session);
continue;
}
ksess = session->kernel_session;
rcu_read_unlock();
}
session_unlock(session);
+ session_put(session);
}
session_unlock_list();
return ret;
error:
session_unlock(session);
+ session_put(session);
session_unlock_list();
return ret;
}
static void update_ust_app(int app_sock)
{
struct ltt_session *sess, *stmp;
+ const struct ltt_session_list *session_list = session_get_list();
/* Consumer is in an ERROR state. Stop any application update. */
if (uatomic_read(&ust_consumerd_state) == CONSUMER_ERROR) {
}
/* For all tracing session(s) */
- cds_list_for_each_entry_safe(sess, stmp, &session_list_ptr->head, list) {
+ cds_list_for_each_entry_safe(sess, stmp, &session_list->head, list) {
struct ust_app *app;
+ if (!session_get(sess)) {
+ continue;
+ }
session_lock(sess);
if (!sess->ust_session) {
goto unlock_session;
rcu_read_unlock();
unlock_session:
session_unlock(sess);
+ session_put(sess);
}
}
{
unsigned int i = 0;
struct ltt_session *session;
+ const struct ltt_session_list *session_list = session_get_list();
DBG("Counting number of available session for UID %d GID %d",
uid, gid);
- cds_list_for_each_entry(session, &session_list_ptr->head, list) {
- /*
- * Only list the sessions the user can control.
- */
- if (!session_access_ok(session, uid, gid)) {
+ cds_list_for_each_entry(session, &session_list->head, list) {
+ if (!session_get(session)) {
continue;
}
- i++;
+ session_lock(session);
+ /* Only count the sessions the user can control. */
+ if (session_access_ok(session, uid, gid) &&
+ !session->destroyed) {
+ i++;
+ }
+ session_unlock(session);
+ session_put(session);
}
return i;
}
if (need_tracing_session) {
if (!session_access_ok(cmd_ctx->session,
LTTNG_SOCK_GET_UID_CRED(&cmd_ctx->creds),
- LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds))) {
+ LTTNG_SOCK_GET_GID_CRED(&cmd_ctx->creds)) ||
+ cmd_ctx->session->destroyed) {
ret = LTTNG_ERR_EPERM;
goto error;
}
}
case LTTNG_DESTROY_SESSION:
{
- ret = cmd_destroy_session(cmd_ctx->session, kernel_poll_pipe[1],
+ ret = cmd_destroy_session(cmd_ctx->session,
notification_thread_handle);
-
- /* Set session to NULL so we do not unlock it after free. */
- cmd_ctx->session = NULL;
break;
}
case LTTNG_LIST_DOMAINS:
setup_error:
if (cmd_ctx->session) {
session_unlock(cmd_ctx->session);
+ session_put(cmd_ctx->session);
}
if (need_tracing_session) {
session_unlock_list();
/* Init UST command queue. */
cds_wfcq_init(&ust_cmd_queue.head, &ust_cmd_queue.tail);
- /*
- * Get session list pointer. This pointer MUST NOT be free'd. This list
- * is statically declared in session.c
- */
- session_list_ptr = session_get_list();
-
cmd_init();
/* Check for the application socket timeout env variable. */
{
int ret = 0;
int fd = lttng_pipe_get_readfd(queue->event_pipe);
- struct ltt_session *session;
char buf;
ret = lttng_read(fd, &buf, 1);
}
for (;;) {
+ struct ltt_session *session;
struct rotation_thread_job *job;
/* Take the queue lock only to pop an element from the list. */
*/
session_unlock_list();
free(job);
+ session_put(session);
continue;
}
session_lock(session);
ret = run_job(job, session, handle->notification_thread_handle);
session_unlock(session);
+ session_put(session);
session_unlock_list();
free(job);
if (ret) {
end_unlock:
session_unlock(session);
+ session_put(session);
end:
return ret;
}
if (!session_access_ok(session,
LTTNG_SOCK_GET_UID_CRED(creds),
- LTTNG_SOCK_GET_GID_CRED(creds))) {
+ LTTNG_SOCK_GET_GID_CRED(creds)) || session->destroyed) {
ret = LTTNG_ERR_EPERM;
goto end;
}
session_lock(session);
ret = save_session(session, attr, creds);
session_unlock(session);
+ session_put(session);
if (ret) {
goto end;
}
struct ltt_session_list *list = session_get_list();
cds_list_for_each_entry(session, &list->head, list) {
+ if (!session_get(session)) {
+ continue;
+ }
session_lock(session);
ret = save_session(session, attr, creds);
session_unlock(session);
-
+ session_put(session);
/* Don't abort if we don't have the required permissions. */
if (ret && ret != LTTNG_ERR_EPERM) {
goto end;
#include <common/common.h>
#include <common/sessiond-comm/sessiond-comm.h>
#include <lttng/location-internal.h>
+#include "lttng-sessiond.h"
+#include "kernel.h"
#include "session.h"
#include "utils.h"
pthread_mutex_unlock(&session->lock);
}
+static
+void session_release(struct urcu_ref *ref)
+{
+ int ret;
+ struct ltt_ust_session *usess;
+ struct ltt_kernel_session *ksess;
+ struct ltt_session *session = container_of(ref, typeof(*session), ref);
+
+ usess = session->ust_session;
+ ksess = session->kernel_session;
+
+ /* Clean kernel session teardown */
+ kernel_destroy_session(ksess);
+
+ /* UST session teardown */
+ if (usess) {
+ /* Close any relayd session */
+ consumer_output_send_destroy_relayd(usess->consumer);
+
+ /* Destroy every UST application related to this session. */
+ ret = ust_app_destroy_trace_all(usess);
+ if (ret) {
+ ERR("Error in ust_app_destroy_trace_all");
+ }
+
+ /* Clean up the rest. */
+ trace_ust_destroy_session(usess);
+ }
+
+ /*
+ * Must notify the kernel thread here to update it's poll set in order to
+ * remove the channel(s)' fd just destroyed.
+ */
+ ret = notify_thread_pipe(kernel_poll_pipe[1]);
+ if (ret < 0) {
+ PERROR("write kernel poll pipe");
+ }
+
+ DBG("Destroying session %s (id %" PRIu64 ")", session->name, session->id);
+ pthread_mutex_destroy(&session->lock);
+
+ consumer_output_put(session->consumer);
+ snapshot_destroy(&session->snapshot);
+ del_session_list(session);
+ del_session_ht(session);
+ free(session);
+}
+
+/*
+ * Acquire a reference to a session.
+ * This function may fail (return false); its return value must be checked.
+ */
+bool session_get(struct ltt_session *session)
+{
+ return urcu_ref_get_unless_zero(&session->ref);
+}
+
+/*
+ * Release a reference to a session.
+ */
+void session_put(struct ltt_session *session)
+{
+ /*
+ * The session list lock must be held as any session_put()
+ * may cause the removal of the session from the session_list.
+ */
+ ASSERT_LOCKED(ltt_session_list.lock);
+ assert(session->ref.refcount);
+ urcu_ref_put(&session->ref, session_release);
+}
+
+/*
+ * Destroy a session.
+ *
+ * This method does not immediately release/free the session as other
+ * components may still hold a reference to the session. However,
+ * the session should no longer be presented to the user.
+ *
+ * Releases the session list's reference to the session
+ * and marks it as destroyed. Iterations on the session list should be
+ * mindful of the "destroyed" flag.
+ */
+void session_destroy(struct ltt_session *session)
+{
+ assert(!session->destroyed);
+ session->destroyed = true;
+ session_put(session);
+}
+
/*
* Return a ltt_session structure ptr that matches name. If no session found,
* NULL is returned. This must be called with the session list lock held using
* session_lock_list and session_unlock_list.
+ * A reference to the session is implicitly acquired by this function.
*/
struct ltt_session *session_find_by_name(const char *name)
{
struct ltt_session *iter;
assert(name);
+ ASSERT_LOCKED(ltt_session_list.lock);
DBG2("Trying to find session by name %s", name);
cds_list_for_each_entry(iter, <t_session_list.head, list) {
- if (strncmp(iter->name, name, NAME_MAX) == 0) {
+ if (!strncmp(iter->name, name, NAME_MAX) &&
+ !iter->destroyed) {
goto found;
}
}
- iter = NULL;
-
+ return NULL;
found:
- return iter;
+ return session_get(iter) ? iter : NULL;
}
/*
struct lttng_ht_iter iter;
struct ltt_session *ls;
+ ASSERT_LOCKED(ltt_session_list.lock);
+
if (!ltt_sessions_ht_by_id) {
goto end;
}
ls = caa_container_of(node, struct ltt_session, node);
DBG3("Session %" PRIu64 " found by id.", id);
- return ls;
+ return session_get(ls) ? ls : NULL;
end:
DBG3("Session %" PRIu64 " NOT found by id", id);
return NULL;
}
-/*
- * Delete session from the session list and free the memory.
- *
- * Return -1 if no session is found. On success, return 1;
- * Should *NOT* be called with RCU read-side lock held.
- */
-int session_destroy(struct ltt_session *session)
-{
- /* Safety check */
- assert(session);
-
- DBG("Destroying session %s (id %" PRIu64 ")", session->name, session->id);
- del_session_list(session);
- pthread_mutex_destroy(&session->lock);
- del_session_ht(session);
-
- consumer_output_put(session->consumer);
- snapshot_destroy(&session->snapshot);
- free(session);
-
- return LTTNG_OK;
-}
-
/*
* Create a brand new session and add it to the session list.
*/
goto error_malloc;
}
+ urcu_ref_init(&new_session->ref);
+
/* Define session name */
if (name != NULL) {
if (snprintf(new_session->name, NAME_MAX, "%s", name) < 0) {
char hostname[HOST_NAME_MAX]; /* Local hostname. */
struct ltt_kernel_session *kernel_session;
struct ltt_ust_session *ust_session;
+ struct urcu_ref ref;
/*
* Protect any read/write on this session data structure. This lock must be
* acquired *before* using any public functions declared below. Use
pthread_mutex_t lock;
struct cds_list_head list;
uint64_t id; /* session unique identifier */
+ /* Indicates if a destroy command has been applied to this session. */
+ bool destroyed;
/* UID/GID of the user owning the session */
uid_t uid;
gid_t gid;
/* Prototypes */
int session_create(char *name, uid_t uid, gid_t gid);
-int session_destroy(struct ltt_session *session);
void session_lock(struct ltt_session *session);
void session_lock_list(void);
void session_unlock(struct ltt_session *session);
void session_unlock_list(void);
+void session_destroy(struct ltt_session *session);
+
+bool session_get(struct ltt_session *session);
+void session_put(struct ltt_session *session);
+
enum consumer_dst_type session_get_consumer_destination_type(
const struct ltt_session *session);
const char *session_get_net_consumer_hostname(
end:
rcu_read_unlock();
+ if (session) {
+ session_put(session);
+ }
}
/*
int ret;
struct buffer_reg_uid *reg_uid;
struct buffer_reg_channel *reg_chan;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
enum lttng_error_code notification_ret;
struct ust_registry_channel *chan_reg;
}
error:
+ if (session) {
+ session_put(session);
+ }
return ret;
}
int ret;
struct ust_registry_session *registry;
enum lttng_error_code cmd_ret;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
uint64_t chan_reg_key;
struct ust_registry_channel *chan_reg;
}
error:
rcu_read_unlock();
+ if (session) {
+ session_put(session);
+ }
return ret;
}
struct ust_app_channel *metadata;
struct consumer_socket *socket;
struct ust_registry_session *registry;
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
assert(ua_sess);
assert(app);
delete_ust_app_channel(-1, metadata, app);
error:
pthread_mutex_unlock(®istry->lock);
+ if (session) {
+ session_put(session);
+ }
return ret;
}
struct lttng_ht_iter iter;
struct ust_app *app;
char pathname[PATH_MAX];
- struct ltt_session *session;
+ struct ltt_session *session = NULL;
uint64_t trace_archive_id;
assert(usess);
error:
rcu_read_unlock();
+ if (session) {
+ session_put(session);
+ }
return status;
}
{
struct ltt_session *iter, *tmp;
+ session_lock_list();
cds_list_for_each_entry_safe(iter, tmp, &session_list->head, list) {
session_destroy(iter);
}
+ session_unlock_list();
/* Session list must be 0 */
assert(!session_list_count());
strncpy(session_name, session->name, sizeof(session_name));
session_name[sizeof(session_name) - 1] = '\0';
- ret = session_destroy(session);
- if (ret == LTTNG_OK) {
- ret = find_session_name(session_name);
- if (ret < 0) {
- /* Success, -1 means that the sesion is NOT found */
- return 0;
- } else {
- /* Fail */
- return -1;
- }
- }
+ session_destroy(session);
+ session_put(session);
- return 0;
+ ret = find_session_name(session_name);
+ if (ret < 0) {
+ /* Success, -1 means that the sesion is NOT found */
+ ret = 0;
+ } else {
+ /* Fail */
+ ret = -1;
+ }
+ return ret;
}
/*
ret = create_one_session(SESSION1);
if (ret < 0) {
/* Fail */
- return -1;
+ ret = -1;
+ goto end;
}
+ session_lock_list();
sess = session_find_by_name(SESSION1);
if (sess) {
/* Success */
- return 0;
+ session_put(sess);
+ session_unlock_list();
+ ret = 0;
+ goto end_unlock;
+ } else {
+ /* Fail */
+ ret = -1;
+ goto end_unlock;
}
-
- /* Fail */
- return -1;
+end_unlock:
+ session_unlock_list();
+end:
+ return ret;
}
void test_session_list(void)
{
struct ltt_session *tmp;
+ session_lock_list();
tmp = session_find_by_name(SESSION1);
ok(tmp != NULL,
session_lock(tmp);
session_unlock(tmp);
+ session_put(tmp);
+ session_unlock_list();
}
void test_destroy_session(void)
{
struct ltt_session *tmp;
+ session_lock_list();
tmp = session_find_by_name(SESSION1);
ok(tmp != NULL,
ok(destroy_one_session(tmp) == 0,
"Destroying session: %s destroyed",
SESSION1);
+ session_unlock_list();
}
void test_duplicate_session(void)
failed = 0;
+ session_lock_list();
for (i = 0; i < MAX_SESSIONS; i++) {
cds_list_for_each_entry_safe(iter, tmp, &session_list->head, list) {
+ assert(session_get(iter));
ret = destroy_one_session(iter);
if (ret < 0) {
diag("session %d destroy failed", i);
}
}
}
+ session_unlock_list();
ok(failed == 0 && session_list_count() == 0,
"Large sessions number: destroyed %u sessions",