summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
eb60c7a)
In per-pid buffering mode, a viewer can attach to a session while it
is active and find it has been closed by the time it requests new
streams. The viewer session's trace chunk is created as a side-effect
of the "get_new_streams" command and can find that the relay_session's
trace chunk has now been closed, causing the creation of the viewer
session trace chunk to fail.
This results in an unexpected error being reported to the live client.
This fix moves the creation of the viewer session's trace chunk to the
"attach" command. If the creation fails, the session is reported as
being "unknown".
Reported-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Tested-by: Francis Deslauriers <francis.deslauriers@efficios.com>
assert(session);
ASSERT_LOCKED(session->lock);
assert(session);
ASSERT_LOCKED(session->lock);
+ if (!viewer_trace_chunk) {
+ ERR("Internal error: viewer session associated with session \"%s\" has a NULL trace chunk",
+ session->session_name);
+ ret = -1;
+ goto error;
+ }
+
if (session->connection_closed) {
*closed = true;
}
if (session->connection_closed) {
*closed = true;
}
error_unlock:
rcu_read_unlock();
error_unlock:
rcu_read_unlock();
}
pthread_mutex_lock(&session->lock);
}
pthread_mutex_lock(&session->lock);
- if (!session->current_trace_chunk) {
- /*
- * Means the session is being destroyed. React the same way
- * as if it could not be found at all.
- */
- DBG("Relay session %" PRIu64 " has no current trace chunk, replying LTTNG_VIEWER_NEW_STREAMS_ERR",
- session_id);
- response.status = htobe32(LTTNG_VIEWER_NEW_STREAMS_ERR);
- goto send_reply_unlock;
- }
-
- if (!conn->viewer_session->current_trace_chunk &&
- session->current_trace_chunk) {
- ret = viewer_session_set_trace_chunk(conn->viewer_session,
- session->current_trace_chunk);
- if (ret) {
- goto error_unlock_session;
- }
- }
ret = make_viewer_streams(session,
conn->viewer_session->current_trace_chunk,
LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent,
ret = make_viewer_streams(session,
conn->viewer_session->current_trace_chunk,
LTTNG_VIEWER_SEEK_LAST, &nb_total, &nb_unsent,
struct lttng_viewer_attach_session_request request;
struct lttng_viewer_attach_session_response response;
struct relay_session *session = NULL;
struct lttng_viewer_attach_session_request request;
struct lttng_viewer_attach_session_response response;
struct relay_session *session = NULL;
+ enum lttng_viewer_attach_return_code viewer_attach_status;
bool closed = false;
uint64_t session_id;
bool closed = false;
uint64_t session_id;
- ret = viewer_session_attach(conn->viewer_session, session);
- if (ret) {
- DBG("Already a viewer attached");
- response.status = htobe32(LTTNG_VIEWER_ATTACH_ALREADY);
+ viewer_attach_status = viewer_session_attach(conn->viewer_session,
+ session);
+ if (viewer_attach_status != LTTNG_VIEWER_ATTACH_OK) {
+ response.status = htobe32(viewer_attach_status);
- if (!conn->viewer_session->current_trace_chunk &&
- session->current_trace_chunk) {
- ret = viewer_session_set_trace_chunk(conn->viewer_session,
- session->current_trace_chunk);
- if (ret) {
- goto end_put_session;
- }
- }
ret = make_viewer_streams(session,
conn->viewer_session->current_trace_chunk, seek_type,
&nb_streams, NULL, NULL, &closed);
ret = make_viewer_streams(session,
conn->viewer_session->current_trace_chunk, seek_type,
&nb_streams, NULL, NULL, &closed);
}
/* The existence of session must be guaranteed by the caller. */
}
/* The existence of session must be guaranteed by the caller. */
-int viewer_session_attach(struct relay_viewer_session *vsession,
+enum lttng_viewer_attach_return_code viewer_session_attach(
+ struct relay_viewer_session *vsession,
struct relay_session *session)
{
struct relay_session *session)
{
+ enum lttng_viewer_attach_return_code viewer_attach_status =
+ LTTNG_VIEWER_ATTACH_OK;
ASSERT_LOCKED(session->lock);
/* Will not fail, as per the ownership guarantee. */
if (!session_get(session)) {
ASSERT_LOCKED(session->lock);
/* Will not fail, as per the ownership guarantee. */
if (!session_get(session)) {
+ viewer_attach_status = LTTNG_VIEWER_ATTACH_UNK;
goto end;
}
if (session->viewer_attached) {
goto end;
}
if (session->viewer_attached) {
+ viewer_attach_status = LTTNG_VIEWER_ATTACH_ALREADY;
+ int ret;
+
+ assert(session->current_trace_chunk);
+ assert(!vsession->current_trace_chunk);
session->viewer_attached = true;
session->viewer_attached = true;
+
+ ret = viewer_session_set_trace_chunk(vsession,
+ session->current_trace_chunk);
+ if (ret) {
+ /*
+ * The live protocol does not define a generic error
+ * value for the "attach" command. The "unknown"
+ * status is used so that the viewer may handle this
+ * failure as if the session didn't exist anymore.
+ */
+ DBG("Failed to create a viewer trace chunk from the current trace chunk of session \"%s\", returning LTTNG_VIEWER_ATTACH_UNK",
+ session->session_name);
+ viewer_attach_status = LTTNG_VIEWER_ATTACH_UNK;
+ }
+ if (viewer_attach_status == LTTNG_VIEWER_ATTACH_OK) {
pthread_mutex_lock(&vsession->session_list_lock);
/* Ownership is transfered to the list. */
cds_list_add_rcu(&session->viewer_session_node,
pthread_mutex_lock(&vsession->session_list_lock);
/* Ownership is transfered to the list. */
cds_list_add_rcu(&session->viewer_session_node,
session_put(session);
}
end:
session_put(session);
}
end:
+ return viewer_attach_status;
}
/* The existence of session must be guaranteed by the caller. */
}
/* The existence of session must be guaranteed by the caller. */
void viewer_session_destroy(struct relay_viewer_session *vsession);
void viewer_session_close(struct relay_viewer_session *vsession);
void viewer_session_destroy(struct relay_viewer_session *vsession);
void viewer_session_close(struct relay_viewer_session *vsession);
-int viewer_session_attach(struct relay_viewer_session *vsession,
+enum lttng_viewer_attach_return_code viewer_session_attach(
+ struct relay_viewer_session *vsession,
struct relay_session *session);
int viewer_session_is_attached(struct relay_viewer_session *vsession,
struct relay_session *session);
struct relay_session *session);
int viewer_session_is_attached(struct relay_viewer_session *vsession,
struct relay_session *session);