sessiond: unregister triggers during clean-up on shutdown
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 26 Jan 2021 23:15:15 +0000 (18:15 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 28 Jan 2021 23:08:04 +0000 (18:08 -0500)
Triggers should be unregistered on sessiond clean-up. This allows the
kernel and user space tracer control code to assume that all event
notifiers have already been destroyed on tear-down and that any
remaining event notifier is the result of a leak.

Moreover, it simplifies the tear down as it is simply handled in the
way a regular trigger unregistration would be.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: Ie821c5162c2fbe9c3d6705f464224c50ae9df1c8

src/bin/lttng-sessiond/kernel.c
src/bin/lttng-sessiond/main.c
src/bin/lttng-sessiond/ust-app.c

index 4bb8045e7ca9e68f078a69cfaa6e2e095b40c911..3216ffcf519f6fc53749b8a10e13d94db8322ac3 100644 (file)
@@ -2065,20 +2065,9 @@ error:
 LTTNG_HIDDEN
 void cleanup_kernel_tracer(void)
 {
-       int ret;
-       struct cds_lfht_iter iter;
-       struct ltt_kernel_event_notifier_rule *rule = NULL;
-
-       rcu_read_lock();
-       cds_lfht_for_each_entry(kernel_token_to_event_notifier_rule_ht, &iter, rule, ht_node) {
-               kernel_disable_event_notifier_rule(rule);
-               trace_kernel_destroy_event_notifier_rule(rule);
-       }
-       rcu_read_unlock();
-
        DBG2("Closing kernel event notifier group notification file descriptor");
        if (kernel_tracer_event_notifier_group_notification_fd >= 0) {
-               ret = notification_thread_command_remove_tracer_event_source(
+               int ret = notification_thread_command_remove_tracer_event_source(
                                notification_thread_handle,
                                kernel_tracer_event_notifier_group_notification_fd);
                if (ret != LTTNG_OK) {
@@ -2095,13 +2084,15 @@ void cleanup_kernel_tracer(void)
        }
 
        if (kernel_token_to_event_notifier_rule_ht) {
-               ret = cds_lfht_destroy(kernel_token_to_event_notifier_rule_ht, NULL);
+               const int ret = cds_lfht_destroy(
+                               kernel_token_to_event_notifier_rule_ht, NULL);
                assert(ret == 0);
        }
 
        DBG2("Closing kernel event notifier group file descriptor");
        if (kernel_tracer_event_notifier_group_fd >= 0) {
-               ret = close(kernel_tracer_event_notifier_group_fd);
+               const int ret = close(kernel_tracer_event_notifier_group_fd);
+
                if (ret) {
                        PERROR("Failed to close kernel event notifier group file descriptor: fd = %d",
                                        kernel_tracer_event_notifier_group_fd);
@@ -2112,7 +2103,8 @@ void cleanup_kernel_tracer(void)
 
        DBG2("Closing kernel fd");
        if (kernel_tracer_fd >= 0) {
-               ret = close(kernel_tracer_fd);
+               const int ret = close(kernel_tracer_fd);
+
                if (ret) {
                        PERROR("Failed to close kernel tracer file descriptor: fd = %d",
                                        kernel_tracer_fd);
index e646a6de5742df1998c38bf794aa68012293f011..9f8c9a332fea3fd28879324e86922af3e8c27edc 100644 (file)
@@ -1254,6 +1254,63 @@ static void destroy_all_sessions_and_wait(void)
        DBG("Destruction of all sessions completed");
 }
 
+static void unregister_all_triggers(void)
+{
+       enum lttng_error_code ret_code;
+       enum lttng_trigger_status trigger_status;
+       struct lttng_triggers *triggers = NULL;
+       unsigned int trigger_count, i;
+       const struct lttng_credentials creds = {
+                       .uid = LTTNG_OPTIONAL_INIT_VALUE(0),
+       };
+
+       DBG("Unregistering all triggers");
+
+       /*
+        * List all triggers as "root" since we wish to unregister all triggers.
+        */
+       ret_code = notification_thread_command_list_triggers(
+                       notification_thread_handle, creds.uid.value, &triggers);
+       if (ret_code != LTTNG_OK) {
+               ERR("Failed to list triggers while unregistering all triggers");
+               goto end;
+       }
+
+       trigger_status = lttng_triggers_get_count(triggers, &trigger_count);
+       assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+       for (i = 0; i < trigger_count; i++) {
+               enum lttng_error_code ret_code;
+               uid_t trigger_owner;
+               const char *trigger_name;
+               const struct lttng_trigger *trigger =
+                               lttng_triggers_get_at_index(triggers, i);
+
+               assert(trigger);
+
+               trigger_status = lttng_trigger_get_owner_uid(
+                               trigger, &trigger_owner);
+               assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+               trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
+               assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+               DBG("Unregistering trigger: trigger owner uid = %d, trigger name = '%s'",
+                               (int) trigger_owner, trigger_name);
+
+               ret_code = cmd_unregister_trigger(
+                               &creds, trigger, notification_thread_handle);
+               if (ret_code != LTTNG_OK) {
+                       ERR("Failed to unregister trigger: trigger owner uid = %d, trigger name = '%s', error: '%s'",
+                                       (int) trigger_owner, trigger_name,
+                                       lttng_strerror(-ret_code));
+                       /* Continue to unregister the remaining triggers. */
+               }
+       }
+end:
+       lttng_triggers_destroy(triggers);
+}
+
 static int run_as_worker_post_fork_cleanup(void *data)
 {
        struct sessiond_config *sessiond_config = data;
@@ -1772,6 +1829,13 @@ stop_threads:
 
        destroy_all_sessions_and_wait();
 
+       /*
+        * At this point no new trigger can be registered (no sessions are
+        * running/rotating) and clients can't connect to the session daemon
+        * anymore. Unregister all triggers.
+        */
+       unregister_all_triggers();
+
        if (register_apps_thread) {
                lttng_thread_shutdown(register_apps_thread);
                lttng_thread_put(register_apps_thread);
index 3a899775dcb62f15f75964626932cc535a570a71..a1891d805e801e19599c69a4d22374465ff62498 100644 (file)
@@ -4314,16 +4314,12 @@ void ust_app_clean_list(void)
        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);
                }
        }
This page took 0.042032 seconds and 4 git commands to generate.