X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-app.c;h=53a6f93178f8616e7302733b9f0a9ef5d6566cd2;hp=2dd69495efaf095b633247b4f24b849a8571076f;hb=700c5a9d4dc7b552926b8ddcbba91cc13312aba0;hpb=b161602a7c4040228777c01342ba5ed7737e7df0 diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 2dd69495e..53a6f9317 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -101,12 +101,14 @@ static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key) { struct ust_app_event *event; const struct ust_app_ht_key *key; + int ev_loglevel_value; assert(node); assert(_key); event = caa_container_of(node, struct ust_app_event, node.node); key = _key; + ev_loglevel_value = event->attr.loglevel; /* Match the 4 elements of the key: name, filter, loglevel, exclusions */ @@ -116,9 +118,10 @@ static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key) } /* Event loglevel. */ - if (event->attr.loglevel != key->loglevel) { + if (ev_loglevel_value != key->loglevel_type) { if (event->attr.loglevel_type == LTTNG_UST_LOGLEVEL_ALL - && key->loglevel == 0 && event->attr.loglevel == -1) { + && key->loglevel_type == 0 && + ev_loglevel_value == -1) { /* * Match is accepted. This is because on event creation, the * loglevel is set to -1 if the event loglevel type is ALL so 0 and @@ -184,7 +187,7 @@ static void add_unique_ust_app_event(struct ust_app_channel *ua_chan, ht = ua_chan->events; key.name = event->attr.name; key.filter = event->filter; - key.loglevel = event->attr.loglevel; + key.loglevel_type = event->attr.loglevel; key.exclusion = event->exclusion; node_ptr = cds_lfht_add_unique(ht->ht, @@ -262,14 +265,17 @@ error: * this function. */ static -void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx) +void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx, + struct ust_app *app) { int ret; assert(ua_ctx); if (ua_ctx->obj) { + pthread_mutex_lock(&app->sock_lock); ret = ustctl_release_object(sock, ua_ctx->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app sock %d release ctx obj handle %d failed with ret %d", sock, ua_ctx->obj->handle, ret); @@ -284,7 +290,8 @@ void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx) * this function. */ static -void delete_ust_app_event(int sock, struct ust_app_event *ua_event) +void delete_ust_app_event(int sock, struct ust_app_event *ua_event, + struct ust_app *app) { int ret; @@ -294,7 +301,9 @@ void delete_ust_app_event(int sock, struct ust_app_event *ua_event) if (ua_event->exclusion != NULL) free(ua_event->exclusion); if (ua_event->obj != NULL) { + pthread_mutex_lock(&app->sock_lock); ret = ustctl_release_object(sock, ua_event->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app sock %d release event obj failed with ret %d", sock, ret); @@ -309,14 +318,17 @@ void delete_ust_app_event(int sock, struct ust_app_event *ua_event) * * Return 0 on success or else a negative value. */ -static int release_ust_app_stream(int sock, struct ust_app_stream *stream) +static int release_ust_app_stream(int sock, struct ust_app_stream *stream, + struct ust_app *app) { int ret = 0; assert(stream); if (stream->obj) { + pthread_mutex_lock(&app->sock_lock); ret = ustctl_release_object(sock, stream->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app sock %d release stream obj failed with ret %d", sock, ret); @@ -333,11 +345,12 @@ static int release_ust_app_stream(int sock, struct ust_app_stream *stream) * this function. */ static -void delete_ust_app_stream(int sock, struct ust_app_stream *stream) +void delete_ust_app_stream(int sock, struct ust_app_stream *stream, + struct ust_app *app) { assert(stream); - (void) release_ust_app_stream(sock, stream); + (void) release_ust_app_stream(sock, stream, app); free(stream); } @@ -380,7 +393,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, /* Wipe stream */ cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) { cds_list_del(&stream->list); - delete_ust_app_stream(sock, stream); + delete_ust_app_stream(sock, stream, app); } /* Wipe context */ @@ -388,7 +401,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, cds_list_del(&ua_ctx->list); ret = lttng_ht_del(ua_chan->ctx, &iter); assert(!ret); - delete_ust_app_ctx(sock, ua_ctx); + delete_ust_app_ctx(sock, ua_ctx, app); } /* Wipe events */ @@ -396,7 +409,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, node.node) { ret = lttng_ht_del(ua_chan->events, &iter); assert(!ret); - delete_ust_app_event(sock, ua_event); + delete_ust_app_event(sock, ua_event, app); } if (ua_chan->session->buffer_type == LTTNG_BUFFER_PER_PID) { @@ -412,7 +425,9 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, iter.iter.node = &ua_chan->ust_objd_node.node; ret = lttng_ht_del(app->ust_objd, &iter); assert(!ret); + pthread_mutex_lock(&app->sock_lock); ret = ustctl_release_object(sock, ua_chan->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app sock %d release channel obj failed with ret %d", sock, ret); @@ -423,6 +438,33 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, call_rcu(&ua_chan->rcu_head, delete_ust_app_channel_rcu); } +int ust_app_register_done(struct ust_app *app) +{ + int ret; + + pthread_mutex_lock(&app->sock_lock); + ret = ustctl_register_done(app->sock); + pthread_mutex_unlock(&app->sock_lock); + return ret; +} + +int ust_app_release_object(struct ust_app *app, struct lttng_ust_object_data *data) +{ + int ret, sock; + + if (app) { + pthread_mutex_lock(&app->sock_lock); + sock = app->sock; + } else { + sock = -1; + } + ret = ustctl_release_object(sock, data); + if (app) { + pthread_mutex_unlock(&app->sock_lock); + } + return ret; +} + /* * Push metadata to consumer socket. * @@ -440,17 +482,20 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry, { int ret; char *metadata_str = NULL; - size_t len, offset; + size_t len, offset, new_metadata_len_sent; ssize_t ret_val; + uint64_t metadata_key; assert(registry); assert(socket); + metadata_key = registry->metadata_key; + /* * Means that no metadata was assigned to the session. This can * happens if no start has been done previously. */ - if (!registry->metadata_key) { + if (!metadata_key) { return 0; } @@ -468,6 +513,7 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry, offset = registry->metadata_len_sent; len = registry->metadata_len - registry->metadata_len_sent; + new_metadata_len_sent = registry->metadata_len; if (len == 0) { DBG3("No metadata to push for metadata key %" PRIu64, registry->metadata_key); @@ -486,13 +532,26 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry, ret_val = -ENOMEM; goto error; } - /* Copy what we haven't send out. */ + /* Copy what we haven't sent out. */ memcpy(metadata_str, registry->metadata + offset, len); - registry->metadata_len_sent += len; push_data: - ret = consumer_push_metadata(socket, registry->metadata_key, + pthread_mutex_unlock(®istry->lock); + /* + * We need to unlock the registry while we push metadata to + * break a circular dependency between the consumerd metadata + * lock and the sessiond registry lock. Indeed, pushing metadata + * to the consumerd awaits that it gets pushed all the way to + * relayd, but doing so requires grabbing the metadata lock. If + * a concurrent metadata request is being performed by + * consumerd, this can try to grab the registry lock on the + * sessiond while holding the metadata lock on the consumer + * daemon. Those push and pull schemes are performed on two + * different bidirectionnal communication sockets. + */ + ret = consumer_push_metadata(socket, metadata_key, metadata_str, len, offset); + pthread_mutex_lock(®istry->lock); if (ret < 0) { /* * There is an acceptable race here between the registry @@ -510,17 +569,29 @@ push_data: */ if (ret == -LTTCOMM_CONSUMERD_CHANNEL_FAIL) { ret = 0; + } else { + ERR("Error pushing metadata to consumer"); } - - /* - * Update back the actual metadata len sent since it - * failed here. - */ - registry->metadata_len_sent -= len; ret_val = ret; goto error_push; + } else { + /* + * Metadata may have been concurrently pushed, since + * we're not holding the registry lock while pushing to + * consumer. This is handled by the fact that we send + * the metadata content, size, and the offset at which + * that metadata belongs. This may arrive out of order + * on the consumer side, and the consumer is able to + * deal with overlapping fragments. The consumer + * supports overlapping fragments, which must be + * contiguous starting from offset 0. We keep the + * largest metadata_len_sent value of the concurrent + * send. + */ + registry->metadata_len_sent = + max_t(size_t, registry->metadata_len_sent, + new_metadata_len_sent); } - free(metadata_str); return len; @@ -714,7 +785,9 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, } if (ua_sess->handle != -1) { + pthread_mutex_lock(&app->sock_lock); ret = ustctl_release_handle(sock, ua_sess->handle); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app sock %d release session handle failed with ret %d", sock, ret); @@ -722,6 +795,8 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, } pthread_mutex_unlock(&ua_sess->lock); + consumer_output_put(ua_sess->consumer); + call_rcu(&ua_sess->rcu_head, delete_ust_app_session_rcu); } @@ -1077,7 +1152,8 @@ error: * Return an ust_app_event object or NULL on error. */ static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht, - char *name, struct lttng_filter_bytecode *filter, int loglevel, + char *name, struct lttng_filter_bytecode *filter, + int loglevel_value, const struct lttng_event_exclusion *exclusion) { struct lttng_ht_iter iter; @@ -1091,7 +1167,7 @@ static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht, /* Setup key for event lookup. */ key.name = name; key.filter = filter; - key.loglevel = loglevel; + key.loglevel_type = loglevel_value; /* lttng_event_exclusion and lttng_ust_event_exclusion structures are similar */ key.exclusion = exclusion; @@ -1122,8 +1198,10 @@ int create_ust_channel_context(struct ust_app_channel *ua_chan, health_code_update(); + pthread_mutex_lock(&app->sock_lock); ret = ustctl_add_context(app->sock, &ua_ctx->ctx, ua_chan->obj, &ua_ctx->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app create channel context failed for app (pid: %d) " @@ -1172,8 +1250,10 @@ int set_ust_event_filter(struct ust_app_event *ua_event, ret = -LTTNG_ERR_NOMEM; goto error; } + pthread_mutex_lock(&app->sock_lock); ret = ustctl_set_filter(app->sock, ust_bytecode, ua_event->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app event %s filter failed for app (pid: %d) " @@ -1242,7 +1322,9 @@ int set_ust_event_exclusion(struct ust_app_event *ua_event, ret = -LTTNG_ERR_NOMEM; goto error; } + pthread_mutex_lock(&app->sock_lock); ret = ustctl_set_exclusion(app->sock, ust_exclusion, ua_event->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app event %s exclusions failed for app (pid: %d) " @@ -1277,7 +1359,9 @@ static int disable_ust_event(struct ust_app *app, health_code_update(); + pthread_mutex_lock(&app->sock_lock); ret = ustctl_disable(app->sock, ua_event->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app event %s disable failed for app (pid: %d) " @@ -1313,7 +1397,9 @@ static int disable_ust_channel(struct ust_app *app, health_code_update(); + pthread_mutex_lock(&app->sock_lock); ret = ustctl_disable(app->sock, ua_chan->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app channel %s disable failed for app (pid: %d) " @@ -1349,7 +1435,9 @@ static int enable_ust_channel(struct ust_app *app, health_code_update(); + pthread_mutex_lock(&app->sock_lock); ret = ustctl_enable(app->sock, ua_chan->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app channel %s enable failed for app (pid: %d) " @@ -1387,7 +1475,9 @@ static int enable_ust_event(struct ust_app *app, health_code_update(); + pthread_mutex_lock(&app->sock_lock); ret = ustctl_enable(app->sock, ua_event->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app event %s enable failed for app (pid: %d) " @@ -1435,7 +1525,10 @@ static int send_channel_pid_to_ust(struct ust_app *app, /* Send channel to the application. */ ret = ust_consumer_send_channel_to_ust(app, ua_sess, ua_chan); - if (ret < 0) { + if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { + ret = -ENOTCONN; /* Caused by app exiting. */ + goto error; + } else if (ret < 0) { goto error; } @@ -1444,12 +1537,15 @@ static int send_channel_pid_to_ust(struct ust_app *app, /* Send all streams to application. */ cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) { ret = ust_consumer_send_stream_to_ust(app, ua_chan, stream); - if (ret < 0) { + if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { + ret = -ENOTCONN; /* Caused by app exiting. */ + goto error; + } else if (ret < 0) { goto error; } /* We don't need the stream anymore once sent to the tracer. */ cds_list_del(&stream->list); - delete_ust_app_stream(-1, stream); + delete_ust_app_stream(-1, stream, app); } /* Flag the channel that it is sent to the application. */ ua_chan->is_sent = 1; @@ -1473,8 +1569,10 @@ int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess, health_code_update(); /* Create UST event on tracer */ + pthread_mutex_lock(&app->sock_lock); ret = ustctl_create_event(app->sock, &ua_event->attr, ua_chan->obj, &ua_event->obj); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("Error ustctl create event %s for app pid: %d with ret %d", @@ -1679,8 +1777,11 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, ua_sess->egid = usess->gid; ua_sess->buffer_type = usess->buffer_type; ua_sess->bits_per_long = app->bits_per_long; + /* There is only one consumer object per session possible. */ + consumer_output_get(usess->consumer); ua_sess->consumer = usess->consumer; + ua_sess->output_traces = usess->output_traces; ua_sess->live_timer_interval = usess->live_timer_interval; copy_channel_attr_to_ustctl(&ua_sess->metadata_attr, @@ -1767,9 +1868,10 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, lttng_ht_add_unique_str(ua_sess->channels, &ua_chan->node); } + return; error: - return; + consumer_output_put(ua_sess->consumer); } /* @@ -2003,7 +2105,9 @@ static int create_ust_app_session(struct ltt_ust_session *usess, health_code_update(); if (ua_sess->handle == -1) { + pthread_mutex_lock(&app->sock_lock); ret = ustctl_create_session(app->sock); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("Creating session for app pid %d with ret %d", @@ -2429,7 +2533,8 @@ error_fd_get: * Return 0 on success or else a negative value. */ static int setup_buffer_reg_streams(struct buffer_reg_channel *reg_chan, - struct ust_app_channel *ua_chan) + struct ust_app_channel *ua_chan, + struct ust_app *app) { int ret = 0; struct ust_app_stream *stream, *stmp; @@ -2458,7 +2563,7 @@ static int setup_buffer_reg_streams(struct buffer_reg_channel *reg_chan, /* We don't need the streams anymore. */ cds_list_del(&stream->list); - delete_ust_app_stream(-1, stream); + delete_ust_app_stream(-1, stream, app); } error: @@ -2522,7 +2627,8 @@ error_create: * Return 0 on success else a negative value. */ static int setup_buffer_reg_channel(struct buffer_reg_session *reg_sess, - struct ust_app_channel *ua_chan, struct buffer_reg_channel *reg_chan) + struct ust_app_channel *ua_chan, struct buffer_reg_channel *reg_chan, + struct ust_app *app) { int ret; @@ -2534,7 +2640,7 @@ static int setup_buffer_reg_channel(struct buffer_reg_session *reg_sess, DBG2("UST app setup buffer registry channel for %s", ua_chan->name); /* Setup all streams for the registry. */ - ret = setup_buffer_reg_streams(reg_chan, ua_chan); + ret = setup_buffer_reg_streams(reg_chan, ua_chan, app); if (ret < 0) { goto error; } @@ -2576,7 +2682,10 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *reg_chan, /* Send channel to the application. */ ret = ust_consumer_send_channel_to_ust(app, ua_sess, ua_chan); - if (ret < 0) { + if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { + ret = -ENOTCONN; /* Caused by app exiting. */ + goto error; + } else if (ret < 0) { goto error; } @@ -2594,7 +2703,13 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *reg_chan, ret = ust_consumer_send_stream_to_ust(app, ua_chan, &stream); if (ret < 0) { - (void) release_ust_app_stream(-1, &stream); + (void) release_ust_app_stream(-1, &stream, app); + if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { + ret = -ENOTCONN; /* Caused by app exiting. */ + goto error_stream_unlock; + } else if (ret < 0) { + goto error_stream_unlock; + } goto error_stream_unlock; } @@ -2602,7 +2717,7 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *reg_chan, * The return value is not important here. This function will output an * error if needed. */ - (void) release_ust_app_stream(-1, &stream); + (void) release_ust_app_stream(-1, &stream, app); } ua_chan->is_sent = 1; @@ -2676,7 +2791,8 @@ static int create_channel_per_uid(struct ust_app *app, /* * Setup the streams and add it to the session registry. */ - ret = setup_buffer_reg_channel(reg_uid->registry, ua_chan, reg_chan); + ret = setup_buffer_reg_channel(reg_uid->registry, + ua_chan, reg_chan, app); if (ret < 0) { ERR("Error setting up UST channel \"%s\"", ua_chan->name); @@ -2688,10 +2804,9 @@ static int create_channel_per_uid(struct ust_app *app, /* Send buffers to the application. */ ret = send_channel_uid_to_ust(reg_chan, app, ua_sess, ua_chan); if (ret < 0) { - /* - * Don't report error to the console, since it may be - * caused by application concurrently exiting. - */ + if (ret != -ENOTCONN) { + ERR("Error sending channel to application"); + } goto error; } @@ -2742,10 +2857,9 @@ static int create_channel_per_pid(struct ust_app *app, ret = send_channel_pid_to_ust(app, ua_sess, ua_chan); if (ret < 0) { - /* - * Don't report error to the console, since it may be - * caused by application concurrently exiting. - */ + if (ret != -ENOTCONN) { + ERR("Error sending channel to application"); + } goto error; } @@ -2759,7 +2873,8 @@ error: * need and send it to the application. This MUST be called with a RCU read * side lock acquired. * - * Return 0 on success or else a negative value. + * Return 0 on success or else a negative value. Returns -ENOTCONN if + * the application exited concurrently. */ static int do_create_channel(struct ust_app *app, struct ltt_ust_session *usess, struct ust_app_session *ua_sess, @@ -2818,7 +2933,8 @@ error: * * Called with UST app session lock and RCU read-side lock held. * - * Return 0 on success or else a negative value. + * Return 0 on success or else a negative value. Returns -ENOTCONN if + * the application exited concurrently. */ static int create_ust_app_channel(struct ust_app_session *ua_sess, struct ltt_ust_channel *uchan, struct ust_app *app, @@ -2922,7 +3038,7 @@ end: error: /* Valid. Calling here is already in a read side lock */ - delete_ust_app_event(-1, ua_event); + delete_ust_app_event(-1, ua_event, app); return ret; } @@ -3113,10 +3229,10 @@ struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock) lta->pid = msg->pid; lttng_ht_node_init_ulong(<a->pid_n, (unsigned long) lta->pid); lta->sock = sock; + pthread_mutex_init(<a->sock_lock, NULL); lttng_ht_node_init_ulong(<a->sock_n, (unsigned long) lta->sock); CDS_INIT_LIST_HEAD(<a->teardown_head); - error: return lta; } @@ -3168,7 +3284,9 @@ int ust_app_version(struct ust_app *app) assert(app); + pthread_mutex_lock(&app->sock_lock); ret = ustctl_tracer_version(app->sock, &app->version); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { ERR("UST app %d version failed with ret %d", app->sock, ret); @@ -3333,12 +3451,14 @@ int ust_app_list_events(struct lttng_event **events) */ continue; } + pthread_mutex_lock(&app->sock_lock); handle = ustctl_tracepoint_list(app->sock); if (handle < 0) { if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) { ERR("UST app list events getting handle failed for app pid %d", app->pid); } + pthread_mutex_unlock(&app->sock_lock); continue; } @@ -3346,6 +3466,8 @@ int ust_app_list_events(struct lttng_event **events) &uiter)) != -LTTNG_UST_ERR_NOENT) { /* Handle ustctl error. */ if (ret < 0) { + int release_ret; + if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { ERR("UST app tp list get failed for app %d with ret %d", app->sock, ret); @@ -3359,6 +3481,11 @@ int ust_app_list_events(struct lttng_event **events) break; } free(tmp_event); + release_ret = ustctl_release_handle(app->sock, handle); + if (release_ret != -LTTNG_UST_ERR_EXITING && release_ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret); + } + pthread_mutex_unlock(&app->sock_lock); goto rcu_error; } @@ -3374,9 +3501,16 @@ int ust_app_list_events(struct lttng_event **events) new_tmp_event = realloc(tmp_event, new_nbmem * sizeof(struct lttng_event)); if (new_tmp_event == NULL) { + int release_ret; + PERROR("realloc ust app events"); free(tmp_event); ret = -ENOMEM; + release_ret = ustctl_release_handle(app->sock, handle); + if (release_ret != -LTTNG_UST_ERR_EXITING && release_ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret); + } + pthread_mutex_unlock(&app->sock_lock); goto rcu_error; } /* Zero the new memory */ @@ -3392,6 +3526,11 @@ int ust_app_list_events(struct lttng_event **events) tmp_event[count].enabled = -1; count++; } + ret = ustctl_release_handle(app->sock, handle); + pthread_mutex_unlock(&app->sock_lock); + if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", app->sock, ret); + } } ret = count; @@ -3439,12 +3578,14 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) */ continue; } + pthread_mutex_lock(&app->sock_lock); handle = ustctl_tracepoint_field_list(app->sock); if (handle < 0) { if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) { ERR("UST app list field getting handle failed for app pid %d", app->pid); } + pthread_mutex_unlock(&app->sock_lock); continue; } @@ -3452,6 +3593,8 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) &uiter)) != -LTTNG_UST_ERR_NOENT) { /* Handle ustctl error. */ if (ret < 0) { + int release_ret; + if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { ERR("UST app tp list field failed for app %d with ret %d", app->sock, ret); @@ -3465,6 +3608,11 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) break; } free(tmp_event); + release_ret = ustctl_release_handle(app->sock, handle); + pthread_mutex_unlock(&app->sock_lock); + if (release_ret != -LTTNG_UST_ERR_EXITING && release_ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret); + } goto rcu_error; } @@ -3480,9 +3628,16 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) new_tmp_event = realloc(tmp_event, new_nbmem * sizeof(struct lttng_event_field)); if (new_tmp_event == NULL) { + int release_ret; + PERROR("realloc ust app event fields"); free(tmp_event); ret = -ENOMEM; + release_ret = ustctl_release_handle(app->sock, handle); + pthread_mutex_unlock(&app->sock_lock); + if (release_ret != -LTTNG_UST_ERR_EXITING && release_ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret); + } goto rcu_error; } /* Zero the new memory */ @@ -3504,6 +3659,11 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) tmp_event[count].event.enabled = -1; count++; } + ret = ustctl_release_handle(app->sock, handle); + pthread_mutex_unlock(&app->sock_lock); + if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { + ERR("Error releasing app handle for app %d with ret %d", app->sock, ret); + } } ret = count; @@ -3713,7 +3873,7 @@ int ust_app_disable_event_glb(struct ltt_ust_session *usess, { int ret = 0; struct lttng_ht_iter iter, uiter; - struct lttng_ht_node_str *ua_chan_node, *ua_event_node; + struct lttng_ht_node_str *ua_chan_node; struct ust_app *app; struct ust_app_session *ua_sess; struct ust_app_channel *ua_chan; @@ -3750,14 +3910,14 @@ int ust_app_disable_event_glb(struct ltt_ust_session *usess, } ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - lttng_ht_lookup(ua_chan->events, (void *)uevent->attr.name, &uiter); - ua_event_node = lttng_ht_iter_get_node_str(&uiter); - if (ua_event_node == NULL) { + ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name, + uevent->filter, uevent->attr.loglevel, + uevent->exclusion); + if (ua_event == NULL) { DBG2("Event %s not found in channel %s for app pid %d." "Skipping", uevent->attr.name, uchan->name, app->pid); continue; } - ua_event = caa_container_of(ua_event_node, struct ust_app_event, node); ret = disable_ust_app_event(ua_sess, ua_event, app); if (ret < 0) { @@ -3819,6 +3979,7 @@ int ust_app_create_channel_glb(struct ltt_ust_session *usess, * or a timeout on it. We can't inform the caller that for a * specific app, the session failed so lets continue here. */ + ret = 0; /* Not an error. */ continue; case -ENOMEM: default: @@ -3845,14 +4006,23 @@ int ust_app_create_channel_glb(struct ltt_ust_session *usess, } pthread_mutex_unlock(&ua_sess->lock); if (ret < 0) { - if (ret == -ENOMEM) { - /* No more memory is a fatal error. Stop right now. */ - goto error_rcu_unlock; - } /* Cleanup the created session if it's the case. */ if (created) { destroy_app_session(app, ua_sess); } + switch (ret) { + case -ENOTCONN: + /* + * The application's socket is not valid. Either a bad socket + * or a timeout on it. We can't inform the caller that for a + * specific app, the session failed so lets continue here. + */ + ret = 0; /* Not an error. */ + continue; + case -ENOMEM: + default: + goto error_rcu_unlock; + } } } @@ -3911,8 +4081,15 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess, /* Lookup channel in the ust app session */ lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter); ua_chan_node = lttng_ht_iter_get_node_str(&uiter); - /* If the channel is not found, there is a code flow error */ - assert(ua_chan_node); + /* + * It is possible that the channel cannot be found is + * the channel/event creation occurs concurrently with + * an application exit. + */ + if (!ua_chan_node) { + pthread_mutex_unlock(&ua_sess->lock); + continue; + } ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); @@ -4047,7 +4224,7 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) ret = run_as_mkdir_recursive(usess->consumer->dst.trace_path, S_IRWXU | S_IRWXG, ua_sess->euid, ua_sess->egid); if (ret < 0) { - if (ret != -EEXIST) { + if (errno != EEXIST) { ERR("Trace directory creation error"); goto error_unlock; } @@ -4067,7 +4244,9 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) skip_setup: /* This start the UST tracing */ + pthread_mutex_lock(&app->sock_lock); ret = ustctl_start_session(app->sock, ua_sess->handle); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("Error starting tracing for app pid: %d (ret: %d)", @@ -4093,7 +4272,9 @@ skip_setup: health_code_update(); /* Quiescent wait after starting trace */ + pthread_mutex_lock(&app->sock_lock); ret = ustctl_wait_quiescent(app->sock); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app wait quiescent failed for app pid %d ret %d", app->pid, ret); @@ -4154,7 +4335,9 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app) health_code_update(); /* This inhibits UST tracing */ + pthread_mutex_lock(&app->sock_lock); ret = ustctl_stop_session(app->sock, ua_sess->handle); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("Error stopping tracing for app pid: %d (ret: %d)", @@ -4174,7 +4357,9 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app) health_code_update(); /* Quiescent wait after stopping trace */ + pthread_mutex_lock(&app->sock_lock); ret = ustctl_wait_quiescent(app->sock); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app wait quiescent failed for app pid %d ret %d", app->pid, ret); @@ -4372,7 +4557,9 @@ static int destroy_trace(struct ltt_ust_session *usess, struct ust_app *app) health_code_update(); /* Quiescent wait after stopping trace */ + pthread_mutex_lock(&app->sock_lock); ret = ustctl_wait_quiescent(app->sock); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app wait quiescent failed for app pid %d ret %d", app->pid, ret); @@ -4501,11 +4688,14 @@ void ust_app_global_create(struct ltt_ust_session *usess, struct ust_app *app) cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter, ua_chan, node.node) { ret = do_create_channel(app, usess, ua_sess, ua_chan); - if (ret < 0) { + if (ret < 0 && ret != -ENOTCONN) { /* - * Stop everything. On error, the application failed, no more - * file descriptor are available or ENOMEM so stopping here is - * the only thing we can do for now. + * Stop everything. On error, the application + * failed, no more file descriptor are available + * or ENOMEM so stopping here is the only thing + * we can do for now. The only exception is + * -ENOTCONN, which indicates that the application + * has exit. */ goto error_unlock; } @@ -4756,7 +4946,9 @@ int ust_app_calibrate_glb(struct lttng_ust_calibrate *calibrate) health_code_update(); + pthread_mutex_lock(&app->sock_lock); ret = ustctl_calibrate(app->sock, calibrate); + pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { switch (ret) { case -ENOSYS: @@ -4985,8 +5177,8 @@ error_rcu_unlock: * On success 0 is returned else a negative value. */ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name, - char *sig, size_t nr_fields, struct ustctl_field *fields, int loglevel, - char *model_emf_uri) + char *sig, size_t nr_fields, struct ustctl_field *fields, + int loglevel_value, char *model_emf_uri) { int ret, ret_code; uint32_t event_id = 0; @@ -5041,9 +5233,9 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name, * three variables MUST NOT be read/write after this. */ ret_code = ust_registry_create_event(registry, chan_reg_key, - sobjd, cobjd, name, sig, nr_fields, fields, loglevel, - model_emf_uri, ua_sess->buffer_type, &event_id, - app); + sobjd, cobjd, name, sig, nr_fields, fields, + loglevel_value, model_emf_uri, ua_sess->buffer_type, + &event_id, app); /* * The return value is returned to ustctl so in case of an error, the @@ -5099,15 +5291,16 @@ int ust_app_recv_notify(int sock) switch (cmd) { case USTCTL_NOTIFY_CMD_EVENT: { - int sobjd, cobjd, loglevel; + int sobjd, cobjd, loglevel_value; char name[LTTNG_UST_SYM_NAME_LEN], *sig, *model_emf_uri; size_t nr_fields; struct ustctl_field *fields; DBG2("UST app ustctl register event received"); - ret = ustctl_recv_register_event(sock, &sobjd, &cobjd, name, &loglevel, - &sig, &nr_fields, &fields, &model_emf_uri); + ret = ustctl_recv_register_event(sock, &sobjd, &cobjd, name, + &loglevel_value, &sig, &nr_fields, &fields, + &model_emf_uri); if (ret < 0) { if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app recv event failed with ret %d", ret); @@ -5124,7 +5317,7 @@ int ust_app_recv_notify(int sock) * to the this function. */ ret = add_event_ust_registry(sock, sobjd, cobjd, name, sig, nr_fields, - fields, loglevel, model_emf_uri); + fields, loglevel_value, model_emf_uri); if (ret < 0) { goto error; }