goto error;
}
- ret = cmd_rotate_session(cmd_ctx->session, &rotate_return);
+ ret = cmd_rotate_session(cmd_ctx->session, &rotate_return,
+ false);
if (ret < 0) {
ret = -ret;
goto error;
* Perform a last rotation on destruction if rotations have
* occurred during the session's lifetime.
*/
- ret = cmd_rotate_session(session, NULL);
+ ret = cmd_rotate_session(session, NULL, false);
if (ret != LTTNG_OK) {
ERR("Failed to perform an implicit rotation as part of the destruction of session \"%s\": %s",
session->name, lttng_strerror(-ret));
if (reply_context) {
reply_context->implicit_rotation_on_destroy = true;
}
- }
+ } else if (session->has_been_started && session->current_trace_chunk &&
+ session_output_supports_trace_chunks(session)) {
+ /*
+ * The user has not triggered a session rotation. However, to
+ * ensure all data has been consumed, the session is rotated
+ * to a 'null' trace chunk before it is destroyed.
+ *
+ * This is a "quiet" rotation meaning that no notification is
+ * emitted and no renaming of the current trace chunk takes
+ * place.
+ */
+ ret = cmd_rotate_session(session, NULL, true);
+ if (ret != LTTNG_OK) {
+ ERR("Failed to perform a quiet rotation as part of the destruction of session \"%s\": %s",
+ session->name, lttng_strerror(-ret));
+ }
+ }
if (session->shm_path[0]) {
/*
* Returns LTTNG_OK on success or else a negative LTTng error code.
*/
int cmd_rotate_session(struct ltt_session *session,
- struct lttng_rotate_session_return *rotate_return)
+ struct lttng_rotate_session_return *rotate_return,
+ bool quiet_rotation)
{
int ret;
uint64_t ongoing_rotation_chunk_id;
}
ret = session_close_trace_chunk(session, chunk_being_archived,
- &((enum lttng_trace_chunk_command_type) {
- LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED}));
+ quiet_rotation ?
+ NULL :
+ &((enum lttng_trace_chunk_command_type){
+ LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED}));
if (ret) {
cmd_ret = LTTNG_ERR_CLOSE_TRACE_CHUNK_FAIL_CONSUMER;
goto error;
}
+ session->quiet_rotation = quiet_rotation;
ret = timer_session_rotation_pending_check_start(session,
DEFAULT_ROTATE_PENDING_TIMER);
if (ret) {
session->chunk_being_archived = chunk_being_archived;
chunk_being_archived = NULL;
- ret = notification_thread_command_session_rotation_ongoing(
- notification_thread_handle,
- session->name, session->uid, session->gid,
- ongoing_rotation_chunk_id);
- if (ret != LTTNG_OK) {
- ERR("Failed to notify notification thread that a session rotation is ongoing for session %s",
- session->name);
- cmd_ret = ret;
+ if (!quiet_rotation) {
+ ret = notification_thread_command_session_rotation_ongoing(
+ notification_thread_handle,
+ session->name, session->uid, session->gid,
+ ongoing_rotation_chunk_id);
+ if (ret != LTTNG_OK) {
+ ERR("Failed to notify notification thread that a session rotation is ongoing for session %s",
+ session->name);
+ cmd_ret = ret;
+ }
}
DBG("Cmd rotate session %s, archive_id %" PRIu64 " sent",
struct notification_thread_handle *notification_thread_handle);
int cmd_rotate_session(struct ltt_session *session,
- struct lttng_rotate_session_return *rotate_return);
+ struct lttng_rotate_session_return *rotate_return,
+ bool quiet_rotation);
int cmd_rotate_get_info(struct ltt_session *session,
struct lttng_rotation_get_info_return *info_return,
uint64_t rotate_id);
check_session_rotation_pending_on_consumers(session,
&rotation_completed);
-
if (!rotation_completed ||
session->rotation_state == LTTNG_ROTATION_STATE_ERROR) {
goto end;
}
session_reset_rotation_state(session, LTTNG_ROTATION_STATE_COMPLETED);
- location = session_get_trace_archive_location(session);
- /* Ownership of location is transferred. */
- ret = notification_thread_command_session_rotation_completed(
- notification_thread_handle,
- session->name,
- session->uid,
- session->gid,
- session->last_archived_chunk_id.value,
- location);
- if (ret != LTTNG_OK) {
- ERR("[rotation-thread] Failed to notify notification thread of completed rotation for session %s",
- session->name);
+ if (!session->quiet_rotation) {
+ location = session_get_trace_archive_location(session);
+ /* Ownership of location is transferred. */
+ ret = notification_thread_command_session_rotation_completed(
+ notification_thread_handle,
+ session->name,
+ session->uid,
+ session->gid,
+ session->last_archived_chunk_id.value,
+ location);
+ if (ret != LTTNG_OK) {
+ ERR("[rotation-thread] Failed to notify notification thread of completed rotation for session %s",
+ session->name);
+ }
}
- if (!session->active) {
+ if (!session->active && !session->quiet_rotation) {
/*
* A stop command was issued during the rotation, it is
* up to the rotation completion check to perform the
DBG("[rotation-thread] Launching scheduled time-based rotation on session \"%s\"",
session->name);
- ret = cmd_rotate_session(session, &rotation_return);
+ ret = cmd_rotate_session(session, &rotation_return, false);
if (ret == LTTNG_OK) {
DBG("[rotation-thread] Scheduled time-based rotation successfully launched on session \"%s\"",
session->name);
goto end_unlock;
}
- ret = cmd_rotate_session(session, NULL);
+ ret = cmd_rotate_session(session, NULL, false);
if (ret == -LTTNG_ERR_ROTATION_PENDING) {
DBG("Rotate already pending, subscribe to the next threshold value");
} else if (ret != LTTNG_OK) {
#include "utils.h"
#include "trace-ust.h"
#include "timer.h"
+#include "cmd.h"
struct ltt_session_destroy_notifier_element {
ltt_session_destroy_notifier notifier;
struct ltt_ust_session *usess;
struct ltt_kernel_session *ksess;
struct ltt_session *session = container_of(ref, typeof(*session), ref);
+ const bool session_published = session->published;
assert(!session->chunk_being_archived);
usess = session->ust_session;
ksess = session->kernel_session;
- session_notify_destruction(session);
- lttng_dynamic_array_reset(&session->destroy_notifiers);
- if (session->current_trace_chunk) {
- ret = session_close_trace_chunk(session, session->current_trace_chunk, NULL);
- if (ret) {
- ERR("Failed to close the current trace chunk of session \"%s\" during its release",
- session->name);
- }
- ret = _session_set_trace_chunk_no_lock_check(session, NULL, NULL);
- if (ret) {
- ERR("Failed to release the current trace chunk of session \"%s\" during its release",
- session->name);
- }
- }
-
/* Clean kernel session teardown */
kernel_destroy_session(ksess);
session->kernel_session = NULL;
pthread_mutex_destroy(&session->lock);
- if (session->published) {
+ if (session_published) {
ASSERT_LOCKED(ltt_session_list.lock);
del_session_list(session);
del_session_ht(session);
- pthread_cond_broadcast(<t_session_list.removal_cond);
}
+ session_notify_destruction(session);
+ lttng_dynamic_array_reset(&session->destroy_notifiers);
free(session->last_archived_chunk_name);
free(session);
+ if (session_published) {
+ /*
+ * Broadcast after free-ing to ensure the memory is
+ * reclaimed before the main thread exits.
+ */
+ pthread_cond_broadcast(<t_session_list.removal_cond);
+ }
}
/*
struct lttng_trace_chunk *chunk_being_archived;
/* Current state of a rotation. */
enum lttng_rotation_state rotation_state;
+ bool quiet_rotation;
char *last_archived_chunk_name;
LTTNG_OPTIONAL(uint64_t) last_archived_chunk_id;
struct lttng_dynamic_array destroy_notifiers;