* Extract the lost packet or discarded events counter when the channel is
* being deleted and store the value in the parent channel so we can
* access it from lttng list and at stop/destroy.
+ *
+ * The session list lock must be held by the caller.
*/
static
void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan)
rcu_read_lock();
session = session_find_by_id(ua_chan->session->tracing_id);
- if (!session) {
- ERR("Missing LTT session to get discarded events");
- goto end;
- }
- if (!session->ust_session) {
- ERR("Missing UST session to get discarded events");
+ if (!session || !session->ust_session) {
+ /*
+ * Not finding the session is not an error because there are
+ * multiple ways the channels can be torn down.
+ *
+ * 1) The session daemon can initiate the destruction of the
+ * ust app session after receiving a destroy command or
+ * during its shutdown/teardown.
+ * 2) The application, since we are in per-pid tracing, is
+ * unregistering and tearing down its ust app session.
+ *
+ * Both paths are protected by the session list lock which
+ * ensures that the accounting of lost packets and discarded
+ * events is done exactly once. The session is then unpublished
+ * from the session list, resulting in this condition.
+ */
goto end;
}
/*
* Delete ust app channel safely. RCU read lock must be held before calling
* this function.
+ *
+ * The session list lock must be held by the caller.
*/
static
void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan,
char *metadata_str = NULL;
size_t len, offset, new_metadata_len_sent;
ssize_t ret_val;
- uint64_t metadata_key;
+ uint64_t metadata_key, metadata_version;
assert(registry);
assert(socket);
offset = registry->metadata_len_sent;
len = registry->metadata_len - registry->metadata_len_sent;
new_metadata_len_sent = registry->metadata_len;
+ metadata_version = registry->metadata_version;
if (len == 0) {
DBG3("No metadata to push for metadata key %" PRIu64,
registry->metadata_key);
* different bidirectionnal communication sockets.
*/
ret = consumer_push_metadata(socket, metadata_key,
- metadata_str, len, offset);
+ metadata_str, len, offset, metadata_version);
pthread_mutex_lock(®istry->lock);
if (ret < 0) {
/*
/*
* Delete ust app session safely. RCU read lock must be held before calling
* this function.
+ *
+ * The session list lock must be held by the caller.
*/
static
void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
int ret, sock;
struct ust_app_session *ua_sess, *tmp_ua_sess;
+ /*
+ * The session list lock must be held during this function to guarantee
+ * the existence of ua_sess.
+ */
+ session_lock_list();
/* Delete ust app sessions info */
sock = app->sock;
app->sock = -1;
DBG2("UST app pid %d deleted", app->pid);
free(app);
+ session_unlock_list();
}
/*
/*
* Delete the session from the application ht and delete the data structure by
* freeing every object inside and releasing them.
+ *
+ * The session list lock must be held by the caller.
*/
static void destroy_app_session(struct ust_app *app,
struct ust_app_session *ua_sess)
uint64_t nb_packets_per_stream)
{
int ret = 0;
- unsigned int snapshot_done = 0;
struct lttng_ht_iter iter;
struct ust_app *app;
char pathname[PATH_MAX];
if (ret < 0) {
goto error;
}
- snapshot_done = 1;
}
break;
}
if (ret < 0) {
goto error;
}
- snapshot_done = 1;
}
break;
}
break;
}
- if (!snapshot_done) {
- /*
- * If no snapshot was made and we are not in the error path, this means
- * that there are no buffers thus no (prior) application to snapshot
- * data from so we have simply NO data.
- */
- ret = -ENODATA;
- }
-
error:
rcu_read_unlock();
return ret;
if (overwrite) {
ret = consumer_get_lost_packets(ust_session_id,
consumer_chan_key, consumer, lost);
+ *discarded = 0;
} else {
ret = consumer_get_discarded_events(ust_session_id,
consumer_chan_key, consumer, discarded);
+ *lost = 0;
}
end:
}
/* Get channel */
- lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
+ lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter);
ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
/* If the session is found for the app, the channel must be there */
assert(ua_chan_node);
if (overwrite) {
ret = consumer_get_lost_packets(usess->id, ua_chan->key,
consumer, lost);
+ *discarded = 0;
goto end;
} else {
ret = consumer_get_discarded_events(usess->id,
ua_chan->key, consumer, discarded);
+ *lost = 0;
goto end;
}
- goto end;
}
end: