- if (!ust_reg_chan->register_done) {
- /*
- * TODO: eventually use the registry event count for
- * this channel to better guess header type for per-pid
- * buffers.
- */
- type = LTTNG_UST_CTL_CHANNEL_HEADER_LARGE;
- ust_reg_chan->nr_ctx_fields = nr_fields;
- ust_reg_chan->ctx_fields = fields;
- fields = NULL;
- ust_reg_chan->header_type = type;
- } else {
- /* Get current already assigned values. */
- type = ust_reg_chan->header_type;
- /*
- * Validate that the context fields match between
- * registry and newcoming application.
- */
- if (!match_lttng_ust_ctl_field_array(ust_reg_chan->ctx_fields,
- ust_reg_chan->nr_ctx_fields,
- fields, nr_fields)) {
- ERR("Registering application channel due to context field mismatch: pid = %d, sock = %d",
- app->pid, app->sock);
- ret_code = -EINVAL;
- goto reply;
- }
- }
+ /*
+ * The application returns the typing information of the channel's
+ * context fields. In per-PID buffering mode, this is the first and only
+ * time we get this information. It is our chance to finalize the
+ * initialiation of the channel and serialize it's layout's description
+ * to the trace's metadata.
+ *
+ * However, in per-UID buffering mode, every application will provide
+ * this information (redundantly). The first time will allow us to
+ * complete the initialization. The following times, we simply validate
+ * that all apps provide the same typing for the context fields as a
+ * sanity check.
+ */
+ try {
+ auto app_context_fields = lsu::create_trace_fields_from_ust_ctl_fields(
+ *locked_registry_session, ust_ctl_context_fields.get(),
+ context_field_count,
+ lst::field_location::root::EVENT_RECORD_COMMON_CONTEXT);
+
+ if (!ust_reg_chan.is_registered()) {
+ lst::type::cuptr event_context = app_context_fields.size() ?
+ lttng::make_unique<lst::structure_type>(
+ 0, std::move(app_context_fields)) :
+ nullptr;
+
+ ust_reg_chan.set_event_context(std::move(event_context));
+ } else {
+ /*
+ * Validate that the context fields match between
+ * registry and newcoming application.
+ */
+ bool context_fields_match;
+ const auto *previous_event_context = ust_reg_chan.get_event_context();
+
+ if (!previous_event_context) {
+ context_fields_match = app_context_fields.size() == 0;
+ } else {
+ const lst::structure_type app_event_context_struct(
+ 0, std::move(app_context_fields));
+
+ context_fields_match = *previous_event_context ==
+ app_event_context_struct;
+ }