X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=lttng-sessiond%2Fust-app.c;h=35688702602eb4fd5d91b9825da95dc4acaf81fd;hp=a30b01dca37ce7515d183430921e79929d66c391;hb=84cd17c63cde7ea5d7a0ad037dd41e8297658812;hpb=ba767faf163cac5db9de0c36051928f3843ff3f9 diff --git a/lttng-sessiond/ust-app.c b/lttng-sessiond/ust-app.c index a30b01dca..356887026 100644 --- a/lttng-sessiond/ust-app.c +++ b/lttng-sessiond/ust-app.c @@ -47,6 +47,7 @@ static void delete_ust_app_event(int sock, struct ust_app_event *ua_event) //} ustctl_release_object(sock, ua_event->obj); + free(ua_event->obj); free(ua_event); } @@ -56,11 +57,9 @@ static void delete_ust_app_event(int sock, struct ust_app_event *ua_event) */ static void delete_ust_app_stream(int sock, struct ltt_ust_stream *stream) { - //TODO - //stream is used for passing to consumer. - //send_channel_streams is responsible for freeing the streams. - //note that this will not play well with flight recorder mode: - //we might need a criterion to discard the streams. + ustctl_release_object(sock, stream->obj); + free(stream->obj); + free(stream); } /* @@ -75,6 +74,7 @@ static void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan) struct ltt_ust_stream *stream, *stmp; cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) { + cds_list_del(&stream->list); delete_ust_app_stream(sock, stream); } @@ -95,6 +95,9 @@ static void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan) ERR("UST app destroy session hashtable failed"); goto error; } + ustctl_release_object(sock, ua_chan->obj); + free(ua_chan->obj); + free(ua_chan); error: return; @@ -112,10 +115,10 @@ static void delete_ust_app_session(int sock, struct ust_app_channel *ua_chan; if (ua_sess->metadata) { - /* - * We do NOT release the stream object and metadata object since they - * are release when fds are sent to the consumer. - */ + ustctl_release_object(sock, ua_sess->metadata->stream_obj); + free(ua_sess->metadata->stream_obj); + ustctl_release_object(sock, ua_sess->metadata->obj); + free(ua_sess->metadata->obj); } cds_lfht_for_each_entry(ua_sess->channels, &iter, ua_chan, node) { @@ -143,6 +146,7 @@ static void delete_ust_app(struct ust_app *app) struct cds_lfht_node *node; struct cds_lfht_iter iter; struct ust_app_session *ua_sess; + int sock; rcu_read_lock(); @@ -167,9 +171,8 @@ static void delete_ust_app(struct ust_app *app) /* Socket is already closed at this point */ /* Delete ust app sessions info */ - if (app->sock_closed) { - app->key.sock = -1; - } + sock = app->key.sock; + app->key.sock = -1; cds_lfht_for_each_entry(app->sessions, &iter, ua_sess, node) { hashtable_del(app->sessions, &iter); @@ -182,9 +185,13 @@ static void delete_ust_app(struct ust_app *app) goto end; } - if (!app->sock_closed) { - close(app->key.sock); - } + /* + * Wait until we have removed the key from the sock hash table + * before closing this socket, otherwise an application could + * re-use the socket ID and race with the teardown, using the + * same hash table entry. + */ + close(sock); DBG2("UST app pid %d deleted", app->key.pid); free(app); @@ -503,17 +510,37 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, * Copy data between a UST app session and a regular LTT session. */ static void shadow_copy_session(struct ust_app_session *ua_sess, - struct ltt_ust_session *usess) + struct ltt_ust_session *usess, + struct ust_app *app) { struct cds_lfht_node *ua_chan_node; struct cds_lfht_iter iter; struct ltt_ust_channel *uchan; struct ust_app_channel *ua_chan; + time_t rawtime; + struct tm *timeinfo; + char datetime[16]; + int ret; + + /* Get date and time for unique app path */ + time(&rawtime); + timeinfo = localtime(&rawtime); + strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo); DBG2("Shadow copy of session handle %d", ua_sess->handle); ua_sess->uid = usess->uid; + ret = snprintf(ua_sess->path, PATH_MAX, + "%s/%s-%d-%s", + usess->pathname, app->name, app->key.pid, + datetime); + if (ret < 0) { + PERROR("asprintf UST shadow copy session"); + /* TODO: We cannot return an error from here.. */ + assert(0); + } + /* TODO: support all UST domain */ /* Iterate over all channels in global domain. */ @@ -541,6 +568,16 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, } } +static +void __lookup_session_by_app(struct ltt_ust_session *usess, + struct ust_app *app, struct cds_lfht_iter *iter) +{ + /* Get right UST app session from app */ + (void) hashtable_lookup(app->sessions, + (void *) ((unsigned long) usess->uid), sizeof(void *), + iter); +} + /* * Return ust app session from the app session hashtable using the UST session * uid. @@ -551,9 +588,8 @@ static struct ust_app_session *lookup_session_by_app( struct cds_lfht_iter iter; struct cds_lfht_node *node; - /* Get right UST app session from app */ - node = hashtable_lookup(app->sessions, - (void *) ((unsigned long) usess->uid), sizeof(void *), &iter); + __lookup_session_by_app(usess, app, &iter); + node = hashtable_iter_get_node(&iter); if (node == NULL) { goto error; } @@ -585,7 +621,7 @@ static struct ust_app_session *create_ust_app_session( /* Only malloc can failed so something is really wrong */ goto error; } - shadow_copy_session(ua_sess, usess); + shadow_copy_session(ua_sess, usess, app); } if (ua_sess->handle == -1) { @@ -727,21 +763,14 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, goto error; } - ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d", - pathname, app->name, app->key.pid); - if (ret < 0) { - PERROR("asprintf UST create stream"); - goto error; - } - - ret = mkdir(ua_sess->metadata->pathname, S_IRWXU | S_IRWXG); + ret = mkdir(ua_sess->path, S_IRWXU | S_IRWXG); if (ret < 0) { PERROR("mkdir UST metadata"); goto error; } - ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, "%s/%s-%d/metadata", - pathname, app->name, app->key.pid); + ret = snprintf(ua_sess->metadata->pathname, PATH_MAX, + "%s/metadata", ua_sess->path); if (ret < 0) { PERROR("asprintf UST create stream"); goto error; @@ -868,10 +897,6 @@ void ust_app_unregister(int sock) goto error; } - /* We got called because the socket was closed on the remote end. */ - close(sock); - /* Using a flag because we still need "sock" as a key. */ - lta->sock_closed = 1; hashtable_del(ust_app_ht, &iter); call_rcu(&node->head, delete_ust_app_rcu); error: @@ -970,8 +995,6 @@ void ust_app_clean_list(void) cds_lfht_for_each(ust_app_ht, &iter, node) { app = caa_container_of(node, struct ust_app, node); - close(app->key.sock); - app->sock_closed = 1; ret = hashtable_del(ust_app_ht, &iter); if (!ret) { @@ -1111,6 +1134,10 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) goto error_rcu_unlock; } + /* upon restart, we skip the setup, already done */ + if (ua_sess->started) + goto skip_setup; + ret = create_ust_app_metadata(ua_sess, usess->pathname, app); if (ret < 0) { goto error_rcu_unlock; @@ -1137,9 +1164,9 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) /* Order is important */ cds_list_add_tail(&ustream->list, &ua_chan->streams.head); - ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s-%d/%s_%u", - usess->pathname, app->name, app->key.pid, - ua_chan->name, ua_chan->streams.count++); + ret = snprintf(ustream->pathname, PATH_MAX, "%s/%s_%u", + ua_sess->path, ua_chan->name, + ua_chan->streams.count++); if (ret < 0) { PERROR("asprintf UST create stream"); continue; @@ -1154,7 +1181,9 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) if (ret < 0) { goto error_rcu_unlock; } + ua_sess->started = 1; +skip_setup: /* This start the UST tracing */ ret = ustctl_start_session(app->key.sock, ua_sess->handle); if (ret < 0) { @@ -1174,6 +1203,100 @@ error_rcu_unlock: return -1; } +/* + * Stop tracing for a specific UST session and app. + */ +int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app) +{ + int ret = 0; + struct ust_app_session *ua_sess; + + DBG("Stopping tracing for ust app pid %d", app->key.pid); + + rcu_read_lock(); + + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == NULL) { + /* Only malloc can failed so something is really wrong */ + goto error_rcu_unlock; + } + +#if 0 /* only useful when periodical flush will be supported */ + /* need to keep a handle on shm in session for this. */ + /* Flush all buffers before stopping */ + ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj); + if (ret < 0) { + ERR("UST metadata flush failed"); + } + + cds_list_for_each_entry(ustchan, &usess->channels.head, list) { + ret = ustctl_flush_buffer(usess->sock, ustchan->obj); + if (ret < 0) { + ERR("UST flush buffer error"); + } + } +#endif + + /* This inhibits UST tracing */ + ret = ustctl_stop_session(app->key.sock, ua_sess->handle); + if (ret < 0) { + ERR("Error stopping tracing for app pid: %d", app->key.pid); + goto error_rcu_unlock; + } + + rcu_read_unlock(); + + /* Quiescent wait after stopping trace */ + ustctl_wait_quiescent(app->key.sock); + + return 0; + +error_rcu_unlock: + rcu_read_unlock(); + return -1; +} + +/* + * Destroy a specific UST session in apps. + */ +int ust_app_destroy_trace(struct ltt_ust_session *usess, struct ust_app *app) +{ + struct ust_app_session *ua_sess; + struct lttng_ust_object_data obj; + struct cds_lfht_iter iter; + struct cds_lfht_node *node; + + DBG("Destroy tracing for ust app pid %d", app->key.pid); + + rcu_read_lock(); + + __lookup_session_by_app(usess, app, &iter); + node = hashtable_iter_get_node(&iter); + if (node == NULL) { + /* Only malloc can failed so something is really wrong */ + goto error_rcu_unlock; + } + ua_sess = caa_container_of(node, struct ust_app_session, node); + hashtable_del(app->sessions, &iter); + delete_ust_app_session(app->key.sock, ua_sess); + obj.handle = ua_sess->handle; + obj.shm_fd = -1; + obj.wait_fd = -1; + obj.memory_map_size = 0; + ustctl_release_object(app->key.sock, &obj); + + rcu_read_unlock(); + + /* Quiescent wait after stopping trace */ + ustctl_wait_quiescent(app->key.sock); + + return 0; + +error_rcu_unlock: + rcu_read_unlock(); + return -1; +} + /* * Start tracing for the UST session. */ @@ -1200,6 +1323,58 @@ int ust_app_start_trace_all(struct ltt_ust_session *usess) return 0; } +/* + * Start tracing for the UST session. + */ +int ust_app_stop_trace_all(struct ltt_ust_session *usess) +{ + int ret = 0; + struct cds_lfht_iter iter; + struct ust_app *app; + + DBG("Stopping all UST traces"); + + rcu_read_lock(); + + cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { + ret = ust_app_stop_trace(usess, app); + if (ret < 0) { + /* Continue to next apps even on error */ + continue; + } + } + + rcu_read_unlock(); + + return 0; +} + +/* + * Destroy app UST session. + */ +int ust_app_destroy_trace_all(struct ltt_ust_session *usess) +{ + int ret = 0; + struct cds_lfht_iter iter; + struct ust_app *app; + + DBG("Destroy all UST traces"); + + rcu_read_lock(); + + cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) { + ret = ust_app_destroy_trace(usess, app); + if (ret < 0) { + /* Continue to next apps even on error */ + continue; + } + } + + rcu_read_unlock(); + + return 0; +} + /* * Add channels/events from UST global domain to registered apps at sock. */