#include <urcu/compiler.h>
#include <signal.h>
+#include <common/bytecode/bytecode.h>
#include <common/compat/errno.h>
#include <common/common.h>
#include <common/hashtable/utils.h>
#include "lttng-sessiond.h"
#include "notification-thread-commands.h"
#include "rotate.h"
+#include "event.h"
struct lttng_ht *ust_app_ht;
struct lttng_ht *ust_app_ht_by_sock;
free(ua_event_notifier_rule->obj);
}
- lttng_event_rule_put(ua_event_notifier_rule->event_rule);
+ lttng_trigger_put(ua_event_notifier_rule->trigger);
call_rcu(&ua_event_notifier_rule->rcu_head,
free_ust_app_event_notifier_rule_rcu);
}
struct ust_app_session *ua_sess, *tmp_ua_sess;
struct lttng_ht_iter iter;
struct ust_app_event_notifier_rule *event_notifier_rule;
+ bool event_notifier_write_fd_is_open;
/*
* The session list lock must be held during this function to guarantee
free(app->event_notifier_group.object);
}
+ event_notifier_write_fd_is_open = lttng_pipe_is_write_open(
+ app->event_notifier_group.event_pipe);
lttng_pipe_destroy(app->event_notifier_group.event_pipe);
+ /*
+ * Release the file descriptors reserved for the event notifier pipe.
+ * The app could be destroyed before the write end of the pipe could be
+ * passed to the application (and closed). In that case, both file
+ * descriptors must be released.
+ */
+ lttng_fd_put(LTTNG_FD_APPS, event_notifier_write_fd_is_open ? 2 : 1);
/*
* Wait until we have deleted the application from the sock hash table
* Allocate a new UST app event notifier rule.
*/
static struct ust_app_event_notifier_rule *alloc_ust_app_event_notifier_rule(
- struct lttng_event_rule *event_rule, uint64_t token)
+ struct lttng_trigger *trigger)
{
enum lttng_event_rule_generate_exclusions_status
generate_exclusion_status;
struct ust_app_event_notifier_rule *ua_event_notifier_rule;
+ struct lttng_condition *condition = NULL;
+ const struct lttng_event_rule *event_rule = NULL;
ua_event_notifier_rule = zmalloc(sizeof(struct ust_app_event_notifier_rule));
if (ua_event_notifier_rule == NULL) {
}
ua_event_notifier_rule->enabled = 1;
- ua_event_notifier_rule->token = token;
- lttng_ht_node_init_u64(&ua_event_notifier_rule->node, token);
+ ua_event_notifier_rule->token = lttng_trigger_get_tracer_token(trigger);
+ lttng_ht_node_init_u64(&ua_event_notifier_rule->node,
+ ua_event_notifier_rule->token);
- /* Get reference of the event rule. */
- if (!lttng_event_rule_get(event_rule)) {
- abort();
- }
+ condition = lttng_trigger_get_condition(trigger);
+ assert(condition);
+ assert(lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
+
+ assert(LTTNG_CONDITION_STATUS_OK == lttng_condition_event_rule_get_rule(condition, &event_rule));
+ assert(event_rule);
+
+ /* Acquire the event notifier's reference to the trigger. */
+ lttng_trigger_get(trigger);
- ua_event_notifier_rule->event_rule = event_rule;
+ ua_event_notifier_rule->trigger = trigger;
ua_event_notifier_rule->filter = lttng_event_rule_get_filter_bytecode(event_rule);
generate_exclusion_status = lttng_event_rule_generate_exclusions(
event_rule, &ua_event_notifier_rule->exclusion);
break;
default:
/* Error occured. */
- ERR("Failed to generate exclusions from event rule while allocating an event notifier rule");
- goto error_put_event_rule;
+ ERR("Failed to generate exclusions from trigger while allocating an event notifier rule");
+ goto error_put_trigger;
}
DBG3("UST app event notifier rule allocated: token = %" PRIu64,
return ua_event_notifier_rule;
-error_put_event_rule:
- lttng_event_rule_put(event_rule);
+error_put_trigger:
+ lttng_trigger_put(trigger);
error:
free(ua_event_notifier_rule);
return NULL;
return NULL;
}
-/*
- * Allocate a filter and copy the given original filter.
- *
- * Return allocated filter or NULL on error.
- */
-static struct lttng_filter_bytecode *copy_filter_bytecode(
- struct lttng_filter_bytecode *orig_f)
-{
- struct lttng_filter_bytecode *filter = NULL;
-
- /* Copy filter bytecode */
- filter = zmalloc(sizeof(*filter) + orig_f->len);
- if (!filter) {
- PERROR("zmalloc alloc filter bytecode");
- goto error;
- }
-
- memcpy(filter, orig_f, sizeof(*filter) + orig_f->len);
-
-error:
- return filter;
-}
-
/*
* Create a liblttng-ust filter bytecode from given bytecode.
*
* Return allocated filter or NULL on error.
*/
static struct lttng_ust_filter_bytecode *create_ust_bytecode_from_bytecode(
- const struct lttng_filter_bytecode *orig_f)
+ const struct lttng_bytecode *orig_f)
{
struct lttng_ust_filter_bytecode *filter = NULL;
goto error;
}
- assert(sizeof(struct lttng_filter_bytecode) ==
+ assert(sizeof(struct lttng_bytecode) ==
sizeof(struct lttng_ust_filter_bytecode));
memcpy(filter, orig_f, sizeof(*filter) + orig_f->len);
error:
* Return an ust_app_event object or NULL on error.
*/
static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht,
- const char *name, const struct lttng_filter_bytecode *filter,
+ const char *name, const struct lttng_bytecode *filter,
int loglevel_value,
const struct lttng_event_exclusion *exclusion)
{
* Set the filter on the tracer.
*/
static int set_ust_object_filter(struct ust_app *app,
- const struct lttng_filter_bytecode *bytecode,
+ const struct lttng_bytecode *bytecode,
struct lttng_ust_object_data *ust_object)
{
int ret;
memset(event_notifier, 0, sizeof(*event_notifier));
- status = lttng_event_rule_tracepoint_get_pattern(rule, &pattern);
- if (status != LTTNG_EVENT_RULE_STATUS_OK) {
- /* At this point, this is a fatal error. */
- abort();
- }
+ if (lttng_event_rule_targets_agent_domain(rule)) {
+ /*
+ * Special event for agents
+ * The actual meat of the event is in the filter that will be
+ * attached later on.
+ * Set the default values for the agent event.
+ */
+ pattern = event_get_default_agent_ust_name(
+ lttng_event_rule_get_domain_type(rule));
+ loglevel = 0;
+ ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
+ } else {
+ status = lttng_event_rule_tracepoint_get_pattern(
+ rule, &pattern);
+ if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+ /* At this point, this is a fatal error. */
+ abort();
+ }
- status = lttng_event_rule_tracepoint_get_log_level_type(
- rule, &loglevel_type);
- if (status != LTTNG_EVENT_RULE_STATUS_OK) {
- /* At this point, this is a fatal error. */
- abort();
- }
+ status = lttng_event_rule_tracepoint_get_log_level_type(
+ rule, &loglevel_type);
+ if (status != LTTNG_EVENT_RULE_STATUS_OK) {
+ /* At this point, this is a fatal error. */
+ abort();
+ }
- switch (loglevel_type) {
- case LTTNG_EVENT_LOGLEVEL_ALL:
- ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
- break;
- case LTTNG_EVENT_LOGLEVEL_RANGE:
- ust_loglevel_type = LTTNG_UST_LOGLEVEL_RANGE;
- break;
- case LTTNG_EVENT_LOGLEVEL_SINGLE:
- ust_loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE;
- break;
- default:
- /* Unknown log level specification type. */
- abort();
- }
+ switch (loglevel_type) {
+ case LTTNG_EVENT_LOGLEVEL_ALL:
+ ust_loglevel_type = LTTNG_UST_LOGLEVEL_ALL;
+ break;
+ case LTTNG_EVENT_LOGLEVEL_RANGE:
+ ust_loglevel_type = LTTNG_UST_LOGLEVEL_RANGE;
+ break;
+ case LTTNG_EVENT_LOGLEVEL_SINGLE:
+ ust_loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE;
+ break;
+ default:
+ /* Unknown log level specification type. */
+ abort();
+ }
- if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
- status = lttng_event_rule_tracepoint_get_log_level(
- rule, &loglevel);
- assert(status == LTTNG_EVENT_RULE_STATUS_OK);
+ if (loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) {
+ status = lttng_event_rule_tracepoint_get_log_level(
+ rule, &loglevel);
+ assert(status == LTTNG_EVENT_RULE_STATUS_OK);
+ }
}
event_notifier->event.instrumentation = LTTNG_UST_TRACEPOINT;
ret = lttng_strncpy(event_notifier->event.name, pattern,
- LTTNG_UST_SYM_NAME_LEN - 1);
+ LTTNG_UST_SYM_NAME_LEN - 1);
if (ret) {
ERR("Failed to copy event rule pattern to notifier: pattern = '%s' ",
pattern);
struct ust_app_event_notifier_rule *ua_event_notifier_rule)
{
int ret = 0;
+ enum lttng_condition_status condition_status;
+ const struct lttng_condition *condition = NULL;
struct lttng_ust_event_notifier event_notifier;
+ const struct lttng_event_rule *event_rule = NULL;
health_code_update();
assert(app->event_notifier_group.object);
- ret = init_ust_event_notifier_from_event_rule(
- ua_event_notifier_rule->event_rule, &event_notifier);
- if (ret) {
- ERR("Failed to initialize UST event notifier from event rule: app = '%s' (ppid: %d)",
- app->name, app->ppid);
- goto error;
- }
+ condition = lttng_trigger_get_const_condition(
+ ua_event_notifier_rule->trigger);
+ assert(condition);
+ assert(lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_EVENT_RULE_HIT);
+
+ condition_status = lttng_condition_event_rule_get_rule(condition, &event_rule);
+ assert(condition_status == LTTNG_CONDITION_STATUS_OK);
+ assert(event_rule);
+ assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_TRACEPOINT);
+ init_ust_event_notifier_from_event_rule(event_rule, &event_notifier);
event_notifier.event.token = ua_event_notifier_rule->token;
/* Create UST event notifier against the tracer. */
/* Copy filter bytecode */
if (uevent->filter) {
- ua_event->filter = copy_filter_bytecode(uevent->filter);
+ ua_event->filter = lttng_bytecode_copy(uevent->filter);
/* Filter might be NULL here in case of ENONEM. */
}
* Called with ust app session mutex held.
*/
static
-int create_ust_app_event_notifier_rule(struct lttng_event_rule *rule,
- struct ust_app *app, uint64_t token)
+int create_ust_app_event_notifier_rule(struct lttng_trigger *trigger,
+ struct ust_app *app)
{
int ret = 0;
struct ust_app_event_notifier_rule *ua_event_notifier_rule;
- ua_event_notifier_rule = alloc_ust_app_event_notifier_rule(rule, token);
+ ua_event_notifier_rule = alloc_ust_app_event_notifier_rule(trigger);
if (ua_event_notifier_rule == NULL) {
ret = -ENOMEM;
goto end;
if (ret == -LTTNG_UST_ERR_EXIST) {
ERR("Tracer for application reported that an event notifier being created already exists: "
"token = \"%" PRIu64 "\", pid = %d, ppid = %d, uid = %d, gid = %d",
- token,
+ lttng_trigger_get_tracer_token(trigger),
app->pid, app->ppid, app->uid,
app->gid);
}
&ua_event_notifier_rule->node);
DBG2("UST app create token event rule completed: app = '%s' (ppid: %d), token = %" PRIu64,
- app->name, app->ppid, token);
+ app->name, app->ppid, lttng_trigger_get_tracer_token(trigger));
end:
return ret;
*/
struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
{
+ int ret;
struct ust_app *lta = NULL;
struct lttng_pipe *event_notifier_event_source_pipe = NULL;
goto error;
}
+ /*
+ * Reserve the two file descriptors of the event source pipe. The write
+ * end will be closed once it is passed to the application, at which
+ * point a single 'put' will be performed.
+ */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret) {
+ ERR("Failed to reserve two file descriptors for the event source pipe while creating a new application instance: app = '%s' (ppid: %d)",
+ msg->name, (int) msg->ppid);
+ goto error;
+ }
+
event_notifier_event_source_pipe = lttng_pipe_open(FD_CLOEXEC);
if (!event_notifier_event_source_pipe) {
PERROR("Failed to open application event source pipe: '%s' (ppid = %d)",
error_free_pipe:
lttng_pipe_destroy(event_notifier_event_source_pipe);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
error:
return NULL;
}
goto error;
}
+ ret = lttng_pipe_write_close(app->event_notifier_group.event_pipe);
+ if (ret) {
+ ERR("Failed to close write end of the application's event source pipe: app = '%s' (ppid = %d)",
+ app->name, app->ppid);
+ goto error;
+ }
+
+ /*
+ * Release the file descriptor that was reserved for the write-end of
+ * the pipe.
+ */
+ lttng_fd_put(LTTNG_FD_APPS, 1);
+
lttng_ret = notification_thread_command_add_tracer_event_source(
notification_thread_handle,
lttng_pipe_get_readfd(app->event_notifier_group.event_pipe),
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);
}
}
looked_up_event_notifier_rule = find_ust_app_event_notifier_rule(
app->token_to_event_notifier_rule_ht, token);
if (!looked_up_event_notifier_rule) {
- ret = create_ust_app_event_notifier_rule(event_rule, app, token);
+ ret = create_ust_app_event_notifier_rule(trigger, app);
if (ret < 0) {
goto end;
}