struct ust_app_session *ua_sess, *tmp_ua_sess;
struct lttng_ht_iter iter;
struct ust_app_event_notifier_rule *event_notifier_rule;
+ bool event_notifier_write_fd_is_open;
/*
* The session list lock must be held during this function to guarantee
free(app->event_notifier_group.object);
}
+ event_notifier_write_fd_is_open = lttng_pipe_is_write_open(
+ app->event_notifier_group.event_pipe);
lttng_pipe_destroy(app->event_notifier_group.event_pipe);
+ /*
+ * Release the file descriptors reserved for the event notifier pipe.
+ * The app could be destroyed before the write end of the pipe could be
+ * passed to the application (and closed). In that case, both file
+ * descriptors must be released.
+ */
+ lttng_fd_put(LTTNG_FD_APPS, event_notifier_write_fd_is_open ? 2 : 1);
/*
* Wait until we have deleted the application from the sock hash table
*/
struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
{
+ int ret;
struct ust_app *lta = NULL;
struct lttng_pipe *event_notifier_event_source_pipe = NULL;
goto error;
}
+ /*
+ * Reserve the two file descriptors of the event source pipe. The write
+ * end will be closed once it is passed to the application, at which
+ * point a single 'put' will be performed.
+ */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret) {
+ ERR("Failed to reserve two file descriptors for the event source pipe while creating a new application instance: app = '%s' (ppid: %d)",
+ msg->name, (int) msg->ppid);
+ goto error;
+ }
+
event_notifier_event_source_pipe = lttng_pipe_open(FD_CLOEXEC);
if (!event_notifier_event_source_pipe) {
PERROR("Failed to open application event source pipe: '%s' (ppid = %d)",
error_free_pipe:
lttng_pipe_destroy(event_notifier_event_source_pipe);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
error:
return NULL;
}
goto error;
}
+ ret = lttng_pipe_write_close(app->event_notifier_group.event_pipe);
+ if (ret) {
+ ERR("Failed to close write end of the application's event source pipe: app = '%s' (ppid = %d)",
+ app->name, app->ppid);
+ goto error;
+ }
+
+ /*
+ * Release the file descriptor that was reserved for the write-end of
+ * the pipe.
+ */
+ lttng_fd_put(LTTNG_FD_APPS, 1);
+
lttng_ret = notification_thread_command_add_tracer_event_source(
notification_thread_handle,
lttng_pipe_get_readfd(app->event_notifier_group.event_pipe),
if (ust_app_ht_by_notify_sock) {
cds_lfht_for_each_entry(ust_app_ht_by_notify_sock->ht, &iter.iter, app,
notify_sock_n.node) {
- struct cds_lfht_node *node;
- struct ust_app *app;
-
- node = cds_lfht_iter_get_node(&iter.iter);
- if (!node) {
- continue;
- }
+ /*
+ * Assert that all notifiers are gone as all triggers
+ * are unregistered prior to this clean-up.
+ */
+ assert(lttng_ht_get_count(app->token_to_event_notifier_rule_ht) == 0);
- app = container_of(node, struct ust_app,
- notify_sock_n.node);
ust_app_notify_sock_unregister(app->notify_sock);
}
}