const void *key)
{
bool match = false;
- const char *name;
+ const char *element_trigger_name;
const char *key_name;
enum lttng_trigger_status status;
const struct lttng_credentials *key_creds;
struct lttng_trigger_ht_element,
node_by_name_uid);
- status = lttng_trigger_get_name(trigger_ht_element->trigger, &name);
- assert(status == LTTNG_TRIGGER_STATUS_OK);
+ status = lttng_trigger_get_name(trigger_ht_element->trigger,
+ &element_trigger_name);
+ element_trigger_name = status == LTTNG_TRIGGER_STATUS_OK ?
+ element_trigger_name : NULL;
status = lttng_trigger_get_name(trigger_key, &key_name);
- assert(status == LTTNG_TRIGGER_STATUS_OK);
+ key_name = status == LTTNG_TRIGGER_STATUS_OK ? key_name : NULL;
- /* Compare the names. */
- if (strcmp(name, key_name) != 0) {
+ /*
+ * Compare the names.
+ * Consider null names as not equal. This is to maintain backwards
+ * compatibility with pre-2.13 anonymous triggers. Multiples anonymous
+ * triggers are allowed for a given user.
+ */
+ if (!element_trigger_name || !key_name) {
+ goto end;
+ }
+
+ if (strcmp(element_trigger_name, key_name) != 0) {
goto end;
}
*/
CDS_INIT_LIST_HEAD(&condition_list_element->node);
condition_list_element->condition = condition;
+ condition = NULL;
cds_list_add(&condition_list_element->node, &client->condition_list);
- client_list = get_client_list_from_condition(state, condition);
+ client_list = get_client_list_from_condition(
+ state, condition_list_element->condition);
if (!client_list) {
/*
* No notification-emiting trigger registered with this
pthread_mutex_lock(&client_list->lock);
cds_list_for_each_entry(trigger_ht_element,
&client_list->triggers_list, client_list_trigger_node) {
- if (evaluate_condition_for_client(trigger_ht_element->trigger, condition,
+ if (evaluate_condition_for_client(trigger_ht_element->trigger, condition_list_element->condition,
client, state)) {
WARN("[notification-thread] Evaluation of a condition on client subscription failed, aborting.");
ret = -1;
if (client_list) {
notification_client_list_put(client_list);
}
+ lttng_condition_destroy(condition);
return ret;
error:
free(condition_list_element);
free(client_list_element);
+ lttng_condition_destroy(condition);
return ret;
}
case LTTNG_TRIGGER_STATUS_OK:
break;
case LTTNG_TRIGGER_STATUS_UNSET:
- *trigger_name = "(unset)";
+ *trigger_name = "(anonymous)";
break;
default:
abort();
/* Not a fatal error if the trigger is not found. */
get_trigger_info_for_log(trigger, &trigger_name, &trigger_owner_uid);
- ERR("Failed to retrieve registered version of trigger: trigger name = '%s', trigger owner uid = %d",
+ DBG("Failed to retrieve registered version of trigger: trigger name = '%s', trigger owner uid = %d",
trigger_name, (int) trigger_owner_uid);
ret = 0;
if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
is_notify = true;
goto end;
- } else if (action_type != LTTNG_ACTION_TYPE_GROUP) {
+ } else if (action_type != LTTNG_ACTION_TYPE_LIST) {
goto end;
}
trigger, &error_counter_index);
if (error_accounting_status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
if (error_accounting_status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE) {
- DBG("Trigger group error accounting counter full.");
+ DBG("Trigger list error accounting counter full.");
ret = LTTNG_ERR_EVENT_NOTIFIER_ERROR_ACCOUNTING_FULL;
} else {
ERR("Error registering trigger for error accounting");
int handle_notification_thread_command_register_trigger(
struct notification_thread_state *state,
struct lttng_trigger *trigger,
+ bool is_trigger_anonymous,
enum lttng_error_code *cmd_result)
{
int ret = 0;
/* Set the trigger's tracer token. */
lttng_trigger_set_tracer_token(trigger, trigger_tracer_token);
- if (lttng_trigger_get_name(trigger, &trigger_name) ==
- LTTNG_TRIGGER_STATUS_UNSET) {
- const enum lttng_error_code ret_code = generate_trigger_name(
- state, trigger, &trigger_name);
+ if (!is_trigger_anonymous) {
+ if (lttng_trigger_get_name(trigger, &trigger_name) ==
+ LTTNG_TRIGGER_STATUS_UNSET) {
+ const enum lttng_error_code ret_code =
+ generate_trigger_name(state, trigger,
+ &trigger_name);
- if (ret_code != LTTNG_OK) {
- /* Fatal error. */
- ret = -1;
- *cmd_result = ret_code;
+ if (ret_code != LTTNG_OK) {
+ /* Fatal error. */
+ ret = -1;
+ *cmd_result = ret_code;
+ goto error;
+ }
+ } else if (trigger_name_taken(state, trigger)) {
+ /* Not a fatal error. */
+ *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
+ ret = 0;
goto error;
}
- } else if (trigger_name_taken(state, trigger)) {
- /* Not a fatal error. */
- *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
- ret = 0;
- goto error;
+ } else {
+ trigger_name = "(anonymous)";
}
condition = lttng_trigger_get_condition(trigger);
trigger,
&trigger_ht_element->node_by_name_uid);
if (node != &trigger_ht_element->node_by_name_uid) {
- /* Not a fatal error, simply report it to the client. */
- cds_lfht_del(state->triggers_ht, &trigger_ht_element->node);
- *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
+ /* Internal error: add to triggers_ht should have failed. */
+ ret = -1;
goto error_free_ht_element;
}
case NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER:
ret = handle_notification_thread_command_register_trigger(state,
cmd->parameters.register_trigger.trigger,
+ cmd->parameters.register_trigger.is_trigger_anonymous,
&cmd->reply_code);
break;
case NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER:
goto end;
}
+ /* Ownership of condition is always transferred. */
if (msg_type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE) {
ret = notification_thread_client_subscribe(
client, condition, state, &status);
goto end;
}
+ if (client->communication.inbound.bytes_to_receive == 0 &&
+ client->communication.inbound.fds_to_receive != 0) {
+ /* Only FDs left to receive. */
+ goto receive_fds;
+ }
+
offset = client->communication.inbound.payload.buffer.size -
client->communication.inbound.bytes_to_receive;
if (client->communication.inbound.expect_creds) {
goto end;
}
+receive_fds:
assert(client->communication.inbound.bytes_to_receive == 0);
/* Receive fds. */
size_t reception_size;
struct lttng_ust_abi_event_notifier_notification ust_notification;
- struct lttng_kernel_event_notifier_notification kernel_notification;
+ struct lttng_kernel_abi_event_notifier_notification kernel_notification;
/* Init lttng_event_notifier_notification */
switch(domain) {
struct cds_lfht_node *node;
struct cds_lfht_iter iter;
struct notification_trigger_tokens_ht_element *element;
- enum lttng_trigger_status trigger_status;
struct lttng_evaluation *evaluation = NULL;
enum action_executor_status executor_status;
struct notification_client_list *client_list = NULL;
- const char *trigger_name;
int ret;
unsigned int capture_count = 0;
struct notification_trigger_tokens_ht_element,
node);
- trigger_status = lttng_trigger_get_name(element->trigger, &trigger_name);
- assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
-
if (lttng_condition_event_rule_matches_get_capture_descriptor_count(
lttng_trigger_get_const_condition(element->trigger),
&capture_count) != LTTNG_CONDITION_STATUS_OK) {