*
*/
+#include "bin/lttng-sessiond/session.h"
#define _LGPL_SOURCE
#include <assert.h>
#include <inttypes.h>
#include <lttng/trigger/trigger-internal.h>
#include <lttng/condition/condition.h>
#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/event-rule.h>
-#include <lttng/condition/event-rule-internal.h>
+#include <lttng/condition/on-event.h>
+#include <lttng/condition/on-event-internal.h>
#include <lttng/event-rule/event-rule.h>
#include <lttng/event-rule/event-rule-internal.h>
#include <lttng/action/action.h>
const struct lttng_domain *domain,
char *channel_name, struct lttng_event *event,
char *filter_expression,
- struct lttng_filter_bytecode *filter,
+ struct lttng_bytecode *filter,
struct lttng_event_exclusion *exclusion,
int wpipe);
* Map enum lttng_ust_output to enum lttng_event_output.
*/
switch (uchan->attr.output) {
- case LTTNG_UST_MMAP:
+ case LTTNG_UST_ABI_MMAP:
channels[i].attr.output = LTTNG_EVENT_MMAP;
break;
default:
cds_lfht_for_each_entry (
agt->events->ht, &iter.iter, agent_event, node.node) {
struct lttng_event event = {
- .enabled = agent_event->enabled,
+ .enabled = AGENT_EVENT_IS_ENABLED(agent_event),
.loglevel = agent_event->loglevel_value,
.loglevel_type = agent_event->loglevel_type,
};
event.enabled = uevent->enabled;
switch (uevent->attr.instrumentation) {
- case LTTNG_UST_TRACEPOINT:
+ case LTTNG_UST_ABI_TRACEPOINT:
event.type = LTTNG_EVENT_TRACEPOINT;
break;
- case LTTNG_UST_PROBE:
+ case LTTNG_UST_ABI_PROBE:
event.type = LTTNG_EVENT_PROBE;
break;
- case LTTNG_UST_FUNCTION:
+ case LTTNG_UST_ABI_FUNCTION:
event.type = LTTNG_EVENT_FUNCTION;
break;
}
event.loglevel = uevent->attr.loglevel;
switch (uevent->attr.loglevel_type) {
- case LTTNG_UST_LOGLEVEL_ALL:
+ case LTTNG_UST_ABI_LOGLEVEL_ALL:
event.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
break;
- case LTTNG_UST_LOGLEVEL_RANGE:
+ case LTTNG_UST_ABI_LOGLEVEL_RANGE:
event.loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
break;
- case LTTNG_UST_LOGLEVEL_SINGLE:
+ case LTTNG_UST_ABI_LOGLEVEL_SINGLE:
event.loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
break;
}
const struct lttng_domain *domain,
char *channel_name, struct lttng_event *event,
char *filter_expression,
- struct lttng_filter_bytecode *filter,
+ struct lttng_bytecode *filter,
struct lttng_event_exclusion *exclusion,
int wpipe, bool internal_event)
{
case LTTNG_EVENT_ALL:
{
char *filter_expression_a = NULL;
- struct lttng_filter_bytecode *filter_a = NULL;
+ struct lttng_bytecode *filter_a = NULL;
/*
* We need to duplicate filter_expression and filter,
{
char *filter_expression_copy = NULL;
- struct lttng_filter_bytecode *filter_copy = NULL;
+ struct lttng_bytecode *filter_copy = NULL;
if (filter) {
const size_t filter_size = sizeof(
- struct lttng_filter_bytecode)
+ struct lttng_bytecode)
+ filter->len;
filter_copy = zmalloc(filter_size);
const struct lttng_domain *domain,
char *channel_name, struct lttng_event *event,
char *filter_expression,
- struct lttng_filter_bytecode *filter,
+ struct lttng_bytecode *filter,
struct lttng_event_exclusion *exclusion,
int wpipe)
{
const struct lttng_domain *domain,
char *channel_name, struct lttng_event *event,
char *filter_expression,
- struct lttng_filter_bytecode *filter,
+ struct lttng_bytecode *filter,
struct lttng_event_exclusion *exclusion,
int wpipe)
{
* then regenerate the metadata. Live and per-pid sessions are not
* supported and return an error.
*
- * Return 0 on success or else a LTTNG_ERR code.
+ * Return LTTNG_OK on success or else a LTTNG_ERR code.
*/
int cmd_regenerate_metadata(struct ltt_session *session)
{
*
* Ask the tracer to regenerate a new statedump.
*
- * Return 0 on success or else a LTTNG_ERR code.
+ * Return LTTNG_OK on success or else a LTTNG_ERR code.
*/
int cmd_regenerate_statedump(struct ltt_session *session)
{
return ret;
}
-static enum lttng_error_code trigger_modifies_event_notifier(
- const struct lttng_trigger *trigger, bool *adds_event_notifier)
+static
+enum lttng_error_code synchronize_tracer_notifier_register(
+ struct notification_thread_handle *notification_thread,
+ struct lttng_trigger *trigger, const struct lttng_credentials *cmd_creds)
{
- enum lttng_error_code ret_code = LTTNG_OK;
- const struct lttng_condition *condition = NULL;
+ enum lttng_error_code ret_code;
+ const struct lttng_condition *condition =
+ lttng_trigger_get_const_condition(trigger);
+ const char *trigger_name;
+ uid_t trigger_owner;
+ enum lttng_trigger_status trigger_status;
+ const enum lttng_domain_type trigger_domain =
+ lttng_trigger_get_underlying_domain_type_restriction(
+ trigger);
- condition = lttng_trigger_get_const_condition(trigger);
- if (!condition) {
- ret_code = LTTNG_ERR_INVALID_TRIGGER;
- goto end;
+ trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_owner);
+ assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+ assert(condition);
+ assert(lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_ON_EVENT);
+
+ trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
+ trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ?
+ trigger_name :
+ "(unnamed)";
+
+ session_lock_list();
+ switch (trigger_domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ {
+ ret_code = kernel_register_event_notifier(trigger, cmd_creds);
+ if (ret_code != LTTNG_OK) {
+ enum lttng_error_code notif_thread_unregister_ret;
+
+ notif_thread_unregister_ret =
+ notification_thread_command_unregister_trigger(
+ notification_thread, trigger);
+
+ if (notif_thread_unregister_ret != LTTNG_OK) {
+ /* Return the original error code. */
+ ERR("Failed to unregister trigger from notification thread during error recovery: trigger name = '%s', trigger owner uid = %d, error code = %d",
+ trigger_name,
+ (int) trigger_owner,
+ ret_code);
+ }
+ }
+ break;
+ }
+ case LTTNG_DOMAIN_UST:
+ ust_app_global_update_all_event_notifier_rules();
+ break;
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
+ {
+ /* Agent domains. */
+ struct agent *agt = agent_find_by_event_notifier_domain(
+ trigger_domain);
+
+ if (!agt) {
+ agt = agent_create(trigger_domain);
+ if (!agt) {
+ ret_code = LTTNG_ERR_NOMEM;
+ goto end_unlock_session_list;
+ }
+
+ agent_add(agt, trigger_agents_ht_by_domain);
+ }
+
+ ret_code = trigger_agent_enable(trigger, agt);
+ if (ret_code != LTTNG_OK) {
+ goto end_unlock_session_list;
+ }
+
+ break;
+ }
+ case LTTNG_DOMAIN_NONE:
+ default:
+ abort();
}
- *adds_event_notifier = lttng_condition_get_type(condition) ==
- LTTNG_CONDITION_TYPE_EVENT_RULE_HIT;
-end:
+ ret_code = LTTNG_OK;
+end_unlock_session_list:
+ session_unlock_list();
return ret_code;
}
struct lttng_trigger **return_trigger)
{
enum lttng_error_code ret_code;
- bool must_update_event_notifier;
const char *trigger_name;
uid_t trigger_owner;
enum lttng_trigger_status trigger_status;
trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
- assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+ trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ?
+ trigger_name : "(unnamed)";
+
trigger_status = lttng_trigger_get_owner_uid(
trigger, &trigger_owner);
assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
ret_code = notification_thread_command_register_trigger(notification_thread,
trigger);
if (ret_code != LTTNG_OK) {
- ERR("Failed to register trigger to notification thread: trigger name = '%s', trigger owner uid = %d, error code = %d",
+ DBG("Failed to register trigger to notification thread: trigger name = '%s', trigger owner uid = %d, error code = %d",
trigger_name, (int) trigger_owner, ret_code);
- goto end_notification_thread;
+ goto end;
}
- ret_code = trigger_modifies_event_notifier(trigger, &must_update_event_notifier);
- if (ret_code != LTTNG_OK) {
- ERR("Failed to determine if event modifies event notifiers: trigger name = '%s', trigger owner uid = %d, error code = %d",
- trigger_name, (int) trigger_owner, ret_code);
- goto end_notification_thread;
- }
+ trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
+ trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ?
+ trigger_name : "(unnamed)";
/*
* Synchronize tracers if the trigger adds an event notifier.
*/
- if (must_update_event_notifier) {
- if (lttng_trigger_get_underlying_domain_type_restriction(
- trigger) == LTTNG_DOMAIN_KERNEL) {
-
- ret_code = kernel_register_event_notifier(
- trigger, cmd_creds);
- if (ret_code != LTTNG_OK) {
- const enum lttng_error_code notif_thread_unregister_ret =
- notification_thread_command_unregister_trigger(
- notification_thread,
- trigger);
-
- if (notif_thread_unregister_ret != LTTNG_OK) {
- /* Return the original error code. */
- ERR("Failed to unregister trigger from notification thread during error recovery: trigger name = '%s', trigger owner uid = %d, error code = %d",
- trigger_name,
- (int) trigger_owner,
- ret_code);
- }
-
- goto end;
- }
- } else {
- ust_app_global_update_all_event_notifier_rules();
+ if (lttng_trigger_needs_tracer_notifier(trigger)) {
+ ret_code = synchronize_tracer_notifier_register(notification_thread,
+ trigger, cmd_creds);
+ if (ret_code != LTTNG_OK) {
+ ERR("Error registering tracer notifier: %s",
+ lttng_strerror(-ret_code));
+ goto end;
}
}
* reference to the trigger so the caller doesn't have to care if those
* are distinct instances or not.
*/
- lttng_trigger_get(trigger);
- *return_trigger = trigger;
-
-end_notification_thread:
- /* Ownership of trigger was transferred. */
- trigger = NULL;
+ if (ret_code == LTTNG_OK) {
+ lttng_trigger_get(trigger);
+ *return_trigger = trigger;
+ /* Ownership of trigger was transferred to caller. */
+ trigger = NULL;
+ }
end:
return ret_code;
}
+static
+enum lttng_error_code synchronize_tracer_notifier_unregister(
+ const struct lttng_trigger *trigger)
+{
+ enum lttng_error_code ret_code;
+ const struct lttng_condition *condition =
+ lttng_trigger_get_const_condition(trigger);
+ const enum lttng_domain_type trigger_domain =
+ lttng_trigger_get_underlying_domain_type_restriction(
+ trigger);
+
+ assert(condition);
+ assert(lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_ON_EVENT);
+
+ session_lock_list();
+ switch (trigger_domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ ret_code = kernel_unregister_event_notifier(trigger);
+ break;
+ case LTTNG_DOMAIN_UST:
+ ust_app_global_update_all_event_notifier_rules();
+ break;
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
+ {
+ /* Agent domains. */
+ struct agent *agt = agent_find_by_event_notifier_domain(
+ trigger_domain);
+
+ /*
+ * This trigger was never registered in the first place. Calling
+ * this function under those circumstances is an internal error.
+ */
+ assert(agt);
+ ret_code = trigger_agent_disable(trigger, agt);
+ if (ret_code != LTTNG_OK) {
+ goto end_unlock_session_list;
+ }
+
+ break;
+ }
+ case LTTNG_DOMAIN_NONE:
+ default:
+ abort();
+ }
+
+ ret_code = LTTNG_OK;
+
+end_unlock_session_list:
+ session_unlock_list();
+ return ret_code;
+}
+
enum lttng_error_code cmd_unregister_trigger(const struct lttng_credentials *cmd_creds,
const struct lttng_trigger *trigger,
struct notification_thread_handle *notification_thread)
{
enum lttng_error_code ret_code;
- bool must_update_event_notifier;
const char *trigger_name;
uid_t trigger_owner;
enum lttng_trigger_status trigger_status;
trigger_status = lttng_trigger_get_name(trigger, &trigger_name);
- assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
- trigger_status = lttng_trigger_get_owner_uid(
- trigger, &trigger_owner);
+ trigger_name = trigger_status == LTTNG_TRIGGER_STATUS_OK ? trigger_name : "(unnamed)";
+ trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_owner);
assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
DBG("Running unregister trigger command: trigger name = '%s', trigger owner uid = %d, command creds uid = %d",
}
}
- ret_code = trigger_modifies_event_notifier(trigger, &must_update_event_notifier);
- if (ret_code != LTTNG_OK) {
- ERR("Failed to determine if event modifies event notifiers: trigger name = '%s', trigger owner uid = %d, error code = %d",
- trigger_name, (int) trigger_owner, ret_code);
- goto end;
- }
-
ret_code = notification_thread_command_unregister_trigger(notification_thread,
trigger);
if (ret_code != LTTNG_OK) {
- ERR("Failed to unregister trigger from notification thread: trigger name = '%s', trigger owner uid = %d, error code = %d",
+ DBG("Failed to unregister trigger from notification thread: trigger name = '%s', trigger owner uid = %d, error code = %d",
trigger_name, (int) trigger_owner, ret_code);
+ goto end;
}
/*
* Synchronize tracers if the trigger removes an event notifier.
+ * Do this even if the trigger unregistration failed to at least stop
+ * the tracers from producing notifications associated with this
+ * event notifier.
*/
- if (must_update_event_notifier) {
- if (lttng_trigger_get_underlying_domain_type_restriction(
- trigger) == LTTNG_DOMAIN_KERNEL) {
-
- ret_code = kernel_unregister_event_notifier(
- trigger);
- } else {
- ust_app_global_update_all_event_notifier_rules();
+ if (lttng_trigger_needs_tracer_notifier(trigger)) {
+ ret_code = synchronize_tracer_notifier_unregister(trigger);
+ if (ret_code != LTTNG_OK) {
+ ERR("Error unregistering trigger to tracer.");
+ goto end;
}
+
}
end:
sizeof(session->shm_path));
session->shm_path[sizeof(session->shm_path) - 1] = '\0';
- return 0;
+ return LTTNG_OK;
}
/*
* 'activate' to false means deactivate the rotation schedule and validate that
* 'new_value' has the same value as the currently active value.
*
- * Return 0 on success or else a positive LTTNG_ERR code.
+ * Return LTTNG_OK on success or else a positive LTTNG_ERR code.
*/
int cmd_rotation_set_schedule(struct ltt_session *session,
bool activate, enum lttng_rotation_schedule_type schedule_type,