X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Faction-executor.cpp;h=23a99a1acbbb7ec94458ad79a5dc7d9a85ba68ee;hb=f149493493fbd8a3efa4748832c03278c96c38ca;hp=032ac11a08de74d0f0657b67086e2bfc7afc99c4;hpb=4ec6f5b6b140c5eaa1b82a2531589e349044aeaa;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/action-executor.cpp b/src/bin/lttng-sessiond/action-executor.cpp index 032ac11a0..23a99a1ac 100644 --- a/src/bin/lttng-sessiond/action-executor.cpp +++ b/src/bin/lttng-sessiond/action-executor.cpp @@ -5,29 +5,29 @@ * */ -#include "action-executor.h" -#include "cmd.h" -#include "health-sessiond.h" -#include "lttng-sessiond.h" -#include "notification-thread-internal.h" -#include "session.h" -#include "thread.h" -#include -#include -#include -#include -#include +#include "action-executor.hpp" +#include "cmd.hpp" +#include "health-sessiond.hpp" +#include "lttng-sessiond.hpp" +#include "notification-thread-internal.hpp" +#include "session.hpp" +#include "thread.hpp" +#include +#include +#include +#include +#include #include -#include +#include #include #include #include #include #include #include -#include +#include #include -#include +#include #include #include #include @@ -36,6 +36,20 @@ #define THREAD_NAME "Action Executor" #define MAX_QUEUED_WORK_COUNT 8192 +struct action_executor { + struct lttng_thread *thread; + struct notification_thread_handle *notification_thread_handle; + struct { + uint64_t pending_count; + struct cds_list_head list; + pthread_cond_t cond; + pthread_mutex_t lock; + } work; + bool should_quit; + uint64_t next_work_item_id; +}; + +namespace { /* * A work item is composed of a dynamic array of sub-items which * represent a flattened, and augmented, version of a trigger's actions. @@ -69,7 +83,6 @@ * trigger object at the moment of execution, if the trigger is found to be * unregistered, the execution is skipped. */ - struct action_work_item { uint64_t id; @@ -94,19 +107,8 @@ struct action_work_subitem { LTTNG_OPTIONAL(uint64_t) session_id; } context; }; +} /* namespace */ -struct action_executor { - struct lttng_thread *thread; - struct notification_thread_handle *notification_thread_handle; - struct { - uint64_t pending_count; - struct cds_list_head list; - pthread_cond_t cond; - pthread_mutex_t lock; - } work; - bool should_quit; - uint64_t next_work_item_id; -}; /* * Only return non-zero on a fatal error that should shut down the action @@ -233,6 +235,15 @@ static int client_handle_transmission_status( case CLIENT_TRANSMISSION_STATUS_COMPLETE: DBG("Successfully sent full notification to client, client_id = %" PRIu64, client->id); + /* + * There is no need to wake the (e)poll thread. If it was waiting for + * "out" events on the client's socket, it will see that no payload + * in queued and will unsubscribe from that event. + * + * In the other cases, we have to wake the the (e)poll thread to either + * handle the error on the client or to get it to monitor the client "out" + * events. + */ update_communication = false; break; case CLIENT_TRANSMISSION_STATUS_QUEUED: @@ -264,7 +275,7 @@ end: static int action_executor_notify_handler(struct action_executor *executor, const struct action_work_item *work_item, - struct action_work_subitem *item) + struct action_work_subitem *item __attribute__((unused))) { return notification_client_list_send_evaluation(work_item->client_list, work_item->trigger, @@ -276,7 +287,7 @@ static int action_executor_notify_handler(struct action_executor *executor, } static int action_executor_start_session_handler( - struct action_executor *executor, + struct action_executor *executor __attribute__((unused)), const struct action_work_item *work_item, struct action_work_subitem *item) { @@ -309,6 +320,7 @@ static int action_executor_start_session_handler( } session_lock_list(); + rcu_read_lock(); session = session_find_by_id(LTTNG_OPTIONAL_GET(item->context.session_id)); if (!session) { DBG("Failed to find session `%s` by name while executing `%s` action of trigger `%s`", @@ -353,13 +365,14 @@ error_unlock_session: session_unlock(session); session_put(session); error_unlock_list: + rcu_read_unlock(); session_unlock_list(); end: return ret; } static int action_executor_stop_session_handler( - struct action_executor *executor, + struct action_executor *executor __attribute__((unused)), const struct action_work_item *work_item, struct action_work_subitem *item) { @@ -392,6 +405,7 @@ static int action_executor_stop_session_handler( } session_lock_list(); + rcu_read_lock(); session = session_find_by_id(LTTNG_OPTIONAL_GET(item->context.session_id)); if (!session) { DBG("Failed to find session `%s` by name while executing `%s` action of trigger `%s`", @@ -436,13 +450,14 @@ error_unlock_session: session_unlock(session); session_put(session); error_unlock_list: + rcu_read_unlock(); session_unlock_list(); end: return ret; } static int action_executor_rotate_session_handler( - struct action_executor *executor, + struct action_executor *executor __attribute__((unused)), const struct action_work_item *work_item, struct action_work_subitem *item) { @@ -475,6 +490,7 @@ static int action_executor_rotate_session_handler( } session_lock_list(); + rcu_read_lock(); session = session_find_by_id(LTTNG_OPTIONAL_GET(item->context.session_id)); if (!session) { DBG("Failed to find session `%s` by name while executing `%s` action of trigger `%s`", @@ -526,13 +542,14 @@ error_unlock_session: session_unlock(session); session_put(session); error_unlock_list: + rcu_read_unlock(); session_unlock_list(); end: return ret; } static int action_executor_snapshot_session_handler( - struct action_executor *executor, + struct action_executor *executor __attribute__((unused)), const struct action_work_item *work_item, struct action_work_subitem *item) { @@ -580,6 +597,7 @@ static int action_executor_snapshot_session_handler( } session_lock_list(); + rcu_read_lock(); session = session_find_by_id(LTTNG_OPTIONAL_GET(item->context.session_id)); if (!session) { DBG("Failed to find session `%s` by name while executing `%s` action of trigger `%s`", @@ -620,14 +638,16 @@ error_unlock_session: session_unlock(session); session_put(session); error_unlock_list: + rcu_read_unlock(); session_unlock_list(); end: return ret; } -static int action_executor_list_handler(struct action_executor *executor, - const struct action_work_item *work_item, - struct action_work_subitem *item) +static int action_executor_list_handler( + struct action_executor *executor __attribute__((unused)), + const struct action_work_item *work_item __attribute__((unused)), + struct action_work_subitem *item __attribute__((unused))) { ERR("Execution of a list action by the action executor should never occur"); abort(); @@ -812,7 +832,7 @@ static void clean_up_action_executor_thread(void *_data) struct action_executor *action_executor_create( struct notification_thread_handle *handle) { - struct action_executor *executor = (action_executor *) zmalloc(sizeof(*executor)); + struct action_executor *executor = zmalloc(); if (!executor) { goto end; @@ -872,6 +892,7 @@ enum action_executor_status action_executor_enqueue_trigger( bool signal = false; LTTNG_ASSERT(trigger); + ASSERT_RCU_READ_LOCKED(); pthread_mutex_lock(&executor->work.lock); /* Check for queue overflow. */ @@ -883,7 +904,7 @@ enum action_executor_status action_executor_enqueue_trigger( goto error_unlock; } - work_item = (action_work_item *) zmalloc(sizeof(*work_item)); + work_item = zmalloc(); if (!work_item) { PERROR("Failed to allocate action executor work item: trigger name = `%s`", get_trigger_name(trigger));