#include "fd-limit.h"
#include "agent-thread.h"
+#include "agent.h"
#include "lttng-sessiond.h"
#include "session.h"
#include "utils.h"
session_unlock_list();
}
-/*
- * Destroy a agent application by socket.
- */
-static void destroy_agent_app(int sock)
-{
- struct agent_app *app;
-
- assert(sock >= 0);
-
- /*
- * Not finding an application is a very important error that should NEVER
- * happen. The hash table deletion is ONLY done through this call even on
- * thread cleanup.
- */
- rcu_read_lock();
- app = agent_find_app_by_sock(sock);
- assert(app);
-
- /* RCU read side lock is assumed to be held by this function. */
- agent_delete_app(app);
-
- /* The application is freed in a RCU call but the socket is closed here. */
- agent_destroy_app(app);
- rcu_read_unlock();
-}
-
-/*
- * Cleanup remaining agent apps in the hash table. This should only be called in
- * the exit path of the thread.
- */
-static void clean_agent_apps_ht(void)
-{
- struct lttng_ht_node_ulong *node;
- struct lttng_ht_iter iter;
-
- DBG3("[agent-thread] Cleaning agent apps ht");
-
- rcu_read_lock();
- cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, node, node) {
- struct agent_app *app;
-
- app = caa_container_of(node, struct agent_app, node);
- destroy_agent_app(app->sock->fd);
- }
- rcu_read_unlock();
-}
-
/*
* Create and init socket from uri.
*/
goto error;
}
- destroy_agent_app(pollfd);
+ agent_destroy_app_by_sock(pollfd);
} else if (revents & (LPOLLIN)) {
int new_fd;
struct agent_app *app = NULL;
ret = lttng_poll_add(&events, new_fd,
LPOLLERR | LPOLLHUP | LPOLLRDHUP);
if (ret < 0) {
- destroy_agent_app(new_fd);
+ agent_destroy_app_by_sock(new_fd);
continue;
}
error_poll_create:
DBG("[agent-thread] is cleaning up and stopping.");
- if (agent_apps_ht_by_sock) {
- clean_agent_apps_ht();
- lttng_ht_destroy(agent_apps_ht_by_sock);
- }
-
rcu_thread_offline();
rcu_unregister_thread();
return NULL;
}
/*
- * Initialize agent subsystem.
+ * Allocate agent_apps_ht_by_sock.
*/
-int agent_setup(void)
+int agent_app_ht_alloc(void)
{
+ int ret = 0;
+
agent_apps_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
if (!agent_apps_ht_by_sock) {
- return -1;
+ ret = -1;
}
- return 0;
+ return ret;
+}
+
+/*
+ * Destroy a agent application by socket.
+ */
+void agent_destroy_app_by_sock(int sock)
+{
+ struct agent_app *app;
+
+ assert(sock >= 0);
+
+ /*
+ * Not finding an application is a very important error that should NEVER
+ * happen. The hash table deletion is ONLY done through this call when the
+ * main sessiond thread is torn down.
+ */
+ rcu_read_lock();
+ app = agent_find_app_by_sock(sock);
+ assert(app);
+
+ /* RCU read side lock is assumed to be held by this function. */
+ agent_delete_app(app);
+
+ /* The application is freed in a RCU call but the socket is closed here. */
+ agent_destroy_app(app);
+ rcu_read_unlock();
+}
+
+/*
+ * Clean-up the agent app hash table and destroy it.
+ */
+void agent_app_ht_clean(void)
+{
+ struct lttng_ht_node_ulong *node;
+ struct lttng_ht_iter iter;
+
+ rcu_read_lock();
+ cds_lfht_for_each_entry(agent_apps_ht_by_sock->ht, &iter.iter, node, node) {
+ struct agent_app *app;
+
+ app = caa_container_of(node, struct agent_app, node);
+ agent_destroy_app_by_sock(app->sock->fd);
+ }
+ rcu_read_unlock();
+
+ lttng_ht_destroy(agent_apps_ht_by_sock);
}
/*
struct lttng_ht_node_u64 node;
};
-/* Setup agent subsystem. */
-int agent_setup(void);
+/* Allocate agent apps hash table */
+int agent_app_ht_alloc(void);
+/* Clean-up agent apps hash table */
+void agent_app_ht_clean(void);
/* Initialize an already allocated agent domain. */
int agent_init(struct agent *agt);
void agent_delete_app(struct agent_app *app);
struct agent_app *agent_find_app_by_sock(int sock);
void agent_destroy_app(struct agent_app *app);
+void agent_destroy_app_by_sock(int sock);
int agent_send_registration_done(struct agent_app *app);
/* Agent action API */
}
}
+ DBG("Cleaning up all agent apps");
+ agent_app_ht_clean();
+
DBG("Closing all UST sockets");
ust_app_clean_list();
buffer_reg_destroy_registries();
goto error;
}
+ /* After this point, we can safely call cleanup() with "goto exit" */
+
/*
* Init UST app hash table. Alloc hash table before this point since
* cleanup() can get called after that point.
*/
ust_app_ht_alloc();
- /* Initialize agent domain subsystem. */
- if ((ret = agent_setup()) < 0) {
- /* ENOMEM at this point. */
- goto error;
+ /*
+ * Initialize agent app hash table. We allocate the hash table here
+ * since cleanup() can get called after this point.
+ */
+ if (agent_app_ht_alloc()) {
+ ERR("Failed to allocate Agent app hash table");
+ ret = -1;
+ goto exit;
}
- /* After this point, we can safely call cleanup() with "goto exit" */
-
/*
* These actions must be executed as root. We do that *after* setting up
* the sockets path because we MUST make the check for another daemon using