- if (ua_chan->attr.overwrite) {
- consumer_get_lost_packets(ua_chan->session->tracing_id,
- ua_chan->key, session->ust_session->consumer,
- &lost);
- } else {
- consumer_get_discarded_events(ua_chan->session->tracing_id,
- ua_chan->key, session->ust_session->consumer,
- &discarded);
- }
- uchan = trace_ust_find_channel_by_name(
- session->ust_session->domain_global.channels,
- ua_chan->name);
- if (!uchan) {
- ERR("Missing UST channel to store discarded counters");
- goto end;
+ try {
+ const auto session = ltt_session::find_session(ua_chan->session->tracing_id);
+
+ if (!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.
+ */
+ return;
+ }
+
+ if (ua_chan->attr.overwrite) {
+ consumer_get_lost_packets(ua_chan->session->tracing_id,
+ ua_chan->key,
+ session->ust_session->consumer,
+ &lost);
+ } else {
+ consumer_get_discarded_events(ua_chan->session->tracing_id,
+ ua_chan->key,
+ session->ust_session->consumer,
+ &discarded);
+ }
+ uchan = trace_ust_find_channel_by_name(session->ust_session->domain_global.channels,
+ ua_chan->name);
+ if (!uchan) {
+ ERR("Missing UST channel to store discarded counters");
+ return;
+ }
+ } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
+ DBG_FMT("Failed to save per-pid lost/discarded counters: {}, location='{}'",
+ ex.what(),
+ ex.source_location);
+ return;