+ len = ustcomm_send_unix_sock(sock, lur, sizeof(*lur));
+ switch (len) {
+ case sizeof(*lur):
+ DBG("message successfully sent");
+ return 0;
+ default:
+ if (len == -ECONNRESET) {
+ DBG("remote end closed connection");
+ return 0;
+ }
+ if (len < 0)
+ return len;
+ DBG("incorrect message size: %zd", len);
+ return -EINVAL;
+ }
+}
+
+static
+void decrement_sem_count(unsigned int count)
+{
+ int ret;
+
+ assert(uatomic_read(&sem_count) >= count);
+
+ if (uatomic_read(&sem_count) <= 0) {
+ return;
+ }
+
+ ret = uatomic_add_return(&sem_count, -count);
+ if (ret == 0) {
+ ret = sem_post(&constructor_wait);
+ assert(!ret);
+ }
+}
+
+static
+int handle_register_done(struct sock_info *sock_info)
+{
+ if (sock_info->registration_done)
+ return 0;
+ sock_info->registration_done = 1;
+
+ decrement_sem_count(1);
+ if (!sock_info->statedump_pending) {
+ sock_info->initial_statedump_done = 1;
+ decrement_sem_count(1);
+ }
+
+ return 0;
+}
+
+static
+int handle_register_failed(struct sock_info *sock_info)
+{
+ if (sock_info->registration_done)
+ return 0;
+ sock_info->registration_done = 1;
+ sock_info->initial_statedump_done = 1;
+
+ decrement_sem_count(2);
+
+ return 0;
+}
+
+/*
+ * Only execute pending statedump after the constructor semaphore has
+ * been posted by the current listener thread. This means statedump will
+ * only be performed after the "registration done" command is received
+ * from this thread's session daemon.
+ *
+ * This ensures we don't run into deadlock issues with the dynamic
+ * loader mutex, which is held while the constructor is called and
+ * waiting on the constructor semaphore. All operations requiring this
+ * dynamic loader lock need to be postponed using this mechanism.
+ *
+ * In a scenario with two session daemons connected to the application,
+ * it is possible that the first listener thread which receives the
+ * registration done command issues its statedump while the dynamic
+ * loader lock is still held by the application constructor waiting on
+ * the semaphore. It will however be allowed to proceed when the
+ * second session daemon sends the registration done command to the
+ * second listener thread. This situation therefore does not produce
+ * a deadlock.
+ */
+static
+void handle_pending_statedump(struct sock_info *sock_info)
+{
+ if (sock_info->registration_done && sock_info->statedump_pending) {
+ sock_info->statedump_pending = 0;
+ pthread_mutex_lock(&ust_fork_mutex);
+ lttng_handle_pending_statedump(sock_info);
+ pthread_mutex_unlock(&ust_fork_mutex);
+
+ if (!sock_info->initial_statedump_done) {
+ sock_info->initial_statedump_done = 1;
+ decrement_sem_count(1);
+ }
+ }
+}
+
+static inline
+const char *bytecode_type_str(uint32_t cmd)
+{
+ switch (cmd) {
+ case LTTNG_UST_CAPTURE:
+ return "capture";
+ case LTTNG_UST_FILTER:
+ return "filter";
+ default:
+ abort();
+ }
+}
+
+static
+int handle_bytecode_recv(struct sock_info *sock_info,
+ int sock, struct ustcomm_ust_msg *lum)
+{
+ struct lttng_ust_bytecode_node *bytecode;
+ enum lttng_ust_bytecode_node_type type;
+ const struct lttng_ust_objd_ops *ops;
+ uint32_t data_size, data_size_max, reloc_offset;
+ uint64_t seqnum;
+ ssize_t len;
+ int ret = 0;
+
+ switch (lum->cmd) {
+ case LTTNG_UST_FILTER:
+ type = LTTNG_UST_BYTECODE_NODE_TYPE_FILTER;
+ data_size = lum->u.filter.data_size;
+ data_size_max = FILTER_BYTECODE_MAX_LEN;
+ reloc_offset = lum->u.filter.reloc_offset;
+ seqnum = lum->u.filter.seqnum;
+ break;
+ case LTTNG_UST_CAPTURE:
+ type = LTTNG_UST_BYTECODE_NODE_TYPE_CAPTURE;
+ data_size = lum->u.capture.data_size;
+ data_size_max = CAPTURE_BYTECODE_MAX_LEN;
+ reloc_offset = lum->u.capture.reloc_offset;
+ seqnum = lum->u.capture.seqnum;
+ break;
+ default:
+ abort();
+ }
+
+ if (data_size > data_size_max) {
+ ERR("Bytecode %s data size is too large: %u bytes",
+ bytecode_type_str(lum->cmd), data_size);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if (reloc_offset > data_size) {
+ ERR("Bytecode %s reloc offset %u is not within data",
+ bytecode_type_str(lum->cmd), reloc_offset);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Allocate the structure AND the `data[]` field. */
+ bytecode = zmalloc(sizeof(*bytecode) + data_size);
+ if (!bytecode) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ bytecode->bc.len = data_size;
+ bytecode->bc.reloc_offset = reloc_offset;
+ bytecode->bc.seqnum = seqnum;
+ bytecode->type = type;
+
+ len = ustcomm_recv_unix_sock(sock, bytecode->bc.data, bytecode->bc.len);