X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-app.c;h=1451963ad41f14cb1809e37594a3960238112819;hb=e9accd4fad532b481ff23af1ef2202c1b5a43c70;hp=7e263a7636f9188f492131a0824b2b4b127f4a89;hpb=b0a5f0fbc428de5cd15a5c86f95a12f32e8c3c88;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 7e263a763..1451963ad 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -364,6 +364,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, /* Wipe context */ cds_lfht_for_each_entry(ua_chan->ctx->ht, &iter.iter, ua_ctx, node.node) { + cds_list_del(&ua_ctx->list); ret = lttng_ht_del(ua_chan->ctx, &iter); assert(!ret); delete_ust_app_ctx(sock, ua_ctx); @@ -388,7 +389,8 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, if (ua_chan->obj != NULL) { /* Remove channel from application UST object descriptor. */ iter.iter.node = &ua_chan->ust_objd_node.node; - lttng_ht_del(app->ust_objd, &iter); + ret = lttng_ht_del(app->ust_objd, &iter); + assert(!ret); ret = ustctl_release_object(sock, ua_chan->obj); if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) { ERR("UST app sock %d release channel obj failed with ret %d", @@ -463,6 +465,25 @@ push_data: ret = consumer_push_metadata(socket, registry->metadata_key, metadata_str, len, offset); if (ret < 0) { + /* + * There is an acceptable race here between the registry metadata key + * assignment and the creation on the consumer. The session daemon can + * concurrently push metadata for this registry while being created on + * the consumer since the metadata key of the registry is assigned + * *before* it is setup to avoid the consumer to ask for metadata that + * could possibly be not found in the session daemon. + * + * The metadata will get pushed either by the session being stopped or + * the consumer requesting metadata if that race is triggered. + */ + if (ret == -LTTCOMM_CONSUMERD_CHANNEL_FAIL) { + ret = 0; + } + + /* Update back the actual metadata len sent since it failed here. */ + pthread_mutex_lock(®istry->lock); + registry->metadata_len_sent -= len; + pthread_mutex_unlock(®istry->lock); ret_val = ret; goto error_push; } @@ -825,6 +846,7 @@ struct ust_app_channel *alloc_ust_app_channel(char *name, lttng_ht_node_init_str(&ua_chan->node, ua_chan->name); CDS_INIT_LIST_HEAD(&ua_chan->streams.head); + CDS_INIT_LIST_HEAD(&ua_chan->ctx_list); /* Copy attributes */ if (attr) { @@ -916,6 +938,8 @@ struct ust_app_ctx *alloc_ust_app_ctx(struct lttng_ust_context *uctx) goto error; } + CDS_INIT_LIST_HEAD(&ua_ctx->list); + if (uctx) { memcpy(&ua_ctx->ctx, uctx, sizeof(ua_ctx->ctx)); } @@ -1051,6 +1075,12 @@ int create_ust_channel_context(struct ust_app_channel *ua_chan, ERR("UST app create channel context failed for app (pid: %d) " "with ret %d", app->pid, ret); } else { + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + ret = 0; DBG3("UST app disable event failed. Application is dead."); } goto error; @@ -1089,6 +1119,12 @@ int set_ust_event_filter(struct ust_app_event *ua_event, ERR("UST app event %s filter failed for app (pid: %d) " "with ret %d", ua_event->attr.name, app->pid, ret); } else { + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + ret = 0; DBG3("UST app filter event failed. Application is dead."); } goto error; @@ -1118,6 +1154,12 @@ static int disable_ust_event(struct ust_app *app, "and session handle %d with ret %d", ua_event->attr.name, app->pid, ua_sess->handle, ret); } else { + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + ret = 0; DBG3("UST app disable event failed. Application is dead."); } goto error; @@ -1148,6 +1190,12 @@ static int disable_ust_channel(struct ust_app *app, "and session handle %d with ret %d", ua_chan->name, app->pid, ua_sess->handle, ret); } else { + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + ret = 0; DBG3("UST app disable channel failed. Application is dead."); } goto error; @@ -1178,6 +1226,12 @@ static int enable_ust_channel(struct ust_app *app, "and session handle %d with ret %d", ua_chan->name, app->pid, ua_sess->handle, ret); } else { + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + ret = 0; DBG3("UST app enable channel failed. Application is dead."); } goto error; @@ -1210,6 +1264,12 @@ static int enable_ust_event(struct ust_app *app, "and session handle %d with ret %d", ua_event->attr.name, app->pid, ua_sess->handle, ret); } else { + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + ret = 0; DBG3("UST app enable event failed. Application is dead."); } goto error; @@ -1290,6 +1350,12 @@ int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess, ERR("Error ustctl create event %s for app pid: %d with ret %d", ua_event->attr.name, app->pid, ret); } else { + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + ret = 0; DBG3("UST app create event failed. Application is dead."); } goto error; @@ -1395,7 +1461,7 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, ua_chan->enabled = uchan->enabled; ua_chan->tracing_channel_id = uchan->id; - cds_lfht_for_each_entry(uchan->ctx->ht, &iter.iter, uctx, node.node) { + cds_list_for_each_entry(uctx, &uchan->ctx_list, list) { ua_ctx = alloc_ust_app_ctx(&uctx->ctx); if (ua_ctx == NULL) { continue; @@ -1403,6 +1469,7 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, lttng_ht_node_init_ulong(&ua_ctx->node, (unsigned long) ua_ctx->ctx.ctx); lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node); + cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list); } /* Copy all events from ltt ust channel to ust app channel */ @@ -1727,6 +1794,13 @@ static int create_ust_app_session(struct ltt_ust_session *usess, app->pid, ret); } else { DBG("UST app creating session failed. Application is dead"); + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. This will get flagged ENOTCONN and the + * caller will handle it. + */ + ret = 0; } delete_ust_app_session(-1, ua_sess, app); if (ret != -ENOMEM) { @@ -1795,6 +1869,7 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess, lttng_ht_node_init_ulong(&ua_ctx->node, (unsigned long) ua_ctx->ctx.ctx); lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node); + cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list); ret = create_ust_channel_context(ua_chan, ua_ctx, app); if (ret < 0) { @@ -2989,11 +3064,17 @@ int ust_app_list_events(struct lttng_event **events) /* Handle ustctl error. */ if (ret < 0) { free(tmp_event); - if (ret != -LTTNG_UST_ERR_EXITING || ret != -EPIPE) { + if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { ERR("UST app tp list get failed for app %d with ret %d", app->sock, ret); } else { DBG3("UST app tp list get failed. Application is dead"); + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. Continue normal execution. + */ + break; } goto rcu_error; } @@ -3083,11 +3164,17 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) /* Handle ustctl error. */ if (ret < 0) { free(tmp_event); - if (ret != -LTTNG_UST_ERR_EXITING || ret != -EPIPE) { + if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { ERR("UST app tp list field failed for app %d with ret %d", app->sock, ret); } else { DBG3("UST app tp list field failed. Application is dead"); + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + break; } goto rcu_error; } @@ -3111,12 +3198,13 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) } memcpy(tmp_event[count].field_name, uiter.field_name, LTTNG_UST_SYM_NAME_LEN); - tmp_event[count].type = uiter.type; + /* Mapping between these enums matches 1 to 1. */ + tmp_event[count].type = (enum lttng_event_field_type) uiter.type; tmp_event[count].nowrite = uiter.nowrite; memcpy(tmp_event[count].event.name, uiter.event_name, LTTNG_UST_SYM_NAME_LEN); tmp_event[count].event.loglevel = uiter.loglevel; - tmp_event[count].event.type = LTTNG_UST_TRACEPOINT; + tmp_event[count].event.type = LTTNG_EVENT_TRACEPOINT; tmp_event[count].event.pid = app->pid; tmp_event[count].event.enabled = -1; count++; @@ -3703,6 +3791,13 @@ skip_setup: app->pid, ret); } else { DBG("UST app start session failed. Application is dead."); + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + pthread_mutex_unlock(&ua_sess->lock); + goto end; } goto error_unlock; } @@ -3778,6 +3873,12 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app) app->pid, ret); } else { DBG("UST app stop session failed. Application is dead."); + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ + goto end_unlock; } goto error_rcu_unlock; } @@ -3801,6 +3902,7 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app) (void) push_metadata(registry, ua_sess->consumer); } +end_unlock: pthread_mutex_unlock(&ua_sess->lock); end_no_session: rcu_read_unlock(); @@ -3855,8 +3957,11 @@ int ust_app_flush_trace(struct ltt_ust_session *usess, struct ust_app *app) } else { DBG3("UST app failed to flush %s. Application is dead.", ua_chan->name); - /* No need to continue. */ - break; + /* + * This is normal behavior, an application can die during the + * creation process. Don't report an error so the execution can + * continue normally. + */ } /* Continuing flushing all buffers */ continue; @@ -4052,7 +4157,7 @@ int ust_app_destroy_trace_all(struct ltt_ust_session *usess) void ust_app_global_update(struct ltt_ust_session *usess, int sock) { int ret = 0; - struct lttng_ht_iter iter, uiter, iter_ctx; + struct lttng_ht_iter iter, uiter; struct ust_app *app; struct ust_app_session *ua_sess = NULL; struct ust_app_channel *ua_chan; @@ -4124,8 +4229,11 @@ void ust_app_global_update(struct ltt_ust_session *usess, int sock) } } - cds_lfht_for_each_entry(ua_chan->ctx->ht, &iter_ctx.iter, ua_ctx, - node.node) { + /* + * Add context using the list so they are enabled in the same order the + * user added them. + */ + cds_list_for_each_entry(ua_ctx, &ua_chan->ctx_list, list) { ret = create_ust_channel_context(ua_chan, ua_ctx, app); if (ret < 0) { goto error_unlock; @@ -4655,7 +4763,8 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name, */ 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); + model_emf_uri, ua_sess->buffer_type, &event_id, + app); /* * The return value is returned to ustctl so in case of an error, the @@ -4883,6 +4992,7 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, struct snapshot_output *output, int wait, unsigned int nb_streams) { int ret = 0; + unsigned int snapshot_done = 0; struct lttng_ht_iter iter; struct ust_app *app; char pathname[PATH_MAX]; @@ -4940,7 +5050,7 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, reg_chan->subbuf_size > max_stream_size) { ret = -EINVAL; DBG3("UST app snapshot record maximum stream size %" PRIu64 - " is smaller than subbuffer size of %" PRIu64, + " is smaller than subbuffer size of %zu", max_stream_size, reg_chan->subbuf_size); goto error; } @@ -4957,6 +5067,7 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, if (ret < 0) { goto error; } + snapshot_done = 1; } break; } @@ -5024,6 +5135,7 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, if (ret < 0) { goto error; } + snapshot_done = 1; } break; } @@ -5032,6 +5144,15 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, 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;