*
*/
-#include <lttng/trigger/trigger-internal.h>
-#include <lttng/condition/condition-internal.h>
-#include <lttng/condition/on-event-internal.h>
-#include <lttng/condition/on-event.h>
-#include <lttng/condition/on-event-internal.h>
-#include <lttng/condition/buffer-usage.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-expr-internal.h>
-#include <lttng/action/action-internal.h>
+#include <assert.h>
#include <common/credentials.h>
-#include <common/payload.h>
-#include <common/payload-view.h>
-#include <lttng/domain.h>
-#include <common/error.h>
#include <common/dynamic-array.h>
+#include <common/error.h>
#include <common/optional.h>
-#include <assert.h>
+#include <common/payload-view.h>
+#include <common/payload.h>
#include <inttypes.h>
+#include <lttng/action/action-internal.h>
+#include <lttng/condition/buffer-usage.h>
+#include <lttng/condition/condition-internal.h>
+#include <lttng/condition/on-event-internal.h>
+#include <lttng/condition/on-event.h>
+#include <lttng/domain.h>
+#include <lttng/event-expr-internal.h>
+#include <lttng/event-rule/event-rule-internal.h>
+#include <lttng/trigger/trigger-internal.h>
+#include <pthread.h>
LTTNG_HIDDEN
bool lttng_trigger_validate(const struct lttng_trigger *trigger)
urcu_ref_init(&trigger->ref);
- trigger->firing_policy.type = LTTNG_TRIGGER_FIRING_POLICY_EVERY_N;
- trigger->firing_policy.threshold = 1;
-
lttng_condition_get(condition);
trigger->condition = condition;
lttng_action_get(action);
trigger->action = action;
+ pthread_mutex_init(&trigger->lock, NULL);
+ trigger->registered = false;
+
end:
return trigger;
}
lttng_action_put(action);
lttng_condition_put(condition);
+ pthread_mutex_destroy(&trigger->lock);
+
free(trigger->name);
free(trigger);
}
lttng_trigger_put(trigger);
}
-static bool is_firing_policy_valid(enum lttng_trigger_firing_policy policy)
-{
- bool valid = false;
-
- switch (policy) {
- case LTTNG_TRIGGER_FIRING_POLICY_EVERY_N:
- case LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N:
- valid = true;
- break;
- default:
- valid = false;
- break;
- }
-
- return valid;
-}
-
LTTNG_HIDDEN
ssize_t lttng_trigger_create_from_payload(
struct lttng_payload_view *src_view,
struct lttng_action *action = NULL;
const struct lttng_trigger_comm *trigger_comm;
const char *name = NULL;
- uint64_t firing_policy_threshold;
- enum lttng_trigger_firing_policy firing_policy;
struct lttng_credentials creds = {
.uid = LTTNG_OPTIONAL_INIT_UNSET,
.gid = LTTNG_OPTIONAL_INIT_UNSET,
offset += sizeof(*trigger_comm);
- firing_policy = trigger_comm->firing_policy_type;
- if (!is_firing_policy_valid(firing_policy)) {
- ret =-1;
- goto end;
- }
-
- firing_policy_threshold = trigger_comm->firing_policy_threshold;
if (trigger_comm->name_length != 0) {
/* Name. */
const struct lttng_payload_view name_view =
}
}
- /* Set the policy. */
- {
- const enum lttng_trigger_status status =
- lttng_trigger_set_firing_policy(trigger,
- firing_policy,
- firing_policy_threshold);
-
- if (status != LTTNG_TRIGGER_STATUS_OK) {
- ret = -1;
- goto end;
- }
- }
-
ret = offset;
error:
}
trigger_comm.name_length = size_name;
- trigger_comm.firing_policy_type = (uint8_t) trigger->firing_policy.type;
- trigger_comm.firing_policy_threshold = (uint64_t) trigger->firing_policy.threshold;
header_offset = payload->buffer.size;
ret = lttng_dynamic_buffer_append(&payload->buffer, &trigger_comm,
bool lttng_trigger_is_equal(
const struct lttng_trigger *a, const struct lttng_trigger *b)
{
- if (a->firing_policy.type != b->firing_policy.type) {
- return false;
- }
-
- if (a->firing_policy.threshold != b->firing_policy.threshold) {
- return false;
- }
-
if (strcmp(a->name, b->name) != 0) {
return false;
}
struct lttng_trigger *trigger, uid_t uid)
{
enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
+ const uid_t euid = geteuid();
const struct lttng_credentials creds = {
.uid = LTTNG_OPTIONAL_INIT_VALUE(uid),
.gid = LTTNG_OPTIONAL_INIT_UNSET,
}
/* Client-side validation only to report a clearer error. */
- if (geteuid() != 0) {
+ if (euid != 0 && euid != uid) {
ret = LTTNG_TRIGGER_STATUS_PERMISSION_DENIED;
goto end;
}
return ret;
}
-enum lttng_trigger_status lttng_trigger_set_firing_policy(
- struct lttng_trigger *trigger,
- enum lttng_trigger_firing_policy policy_type,
- uint64_t threshold)
-{
- enum lttng_trigger_status ret = LTTNG_TRIGGER_STATUS_OK;
- assert(trigger);
-
- if (threshold < 1) {
- ret = LTTNG_TRIGGER_STATUS_INVALID;
- goto end;
- }
-
- trigger->firing_policy.type = policy_type;
- trigger->firing_policy.threshold = threshold;
-
-end:
- return ret;
-}
-
-enum lttng_trigger_status lttng_trigger_get_firing_policy(
- const struct lttng_trigger *trigger,
- enum lttng_trigger_firing_policy *policy_type,
- uint64_t *threshold)
-{
- enum lttng_trigger_status status = LTTNG_TRIGGER_STATUS_OK;
-
- if (!trigger || !policy_type || !threshold) {
- status = LTTNG_TRIGGER_STATUS_INVALID;
- goto end;
- }
-
- *policy_type = trigger->firing_policy.type;
- *threshold = trigger->firing_policy.threshold;
-
-end:
- return status;
-}
-
-LTTNG_HIDDEN
-bool lttng_trigger_should_fire(const struct lttng_trigger *trigger)
-{
- bool ready_to_fire = false;
-
- assert(trigger);
-
- switch (trigger->firing_policy.type) {
- case LTTNG_TRIGGER_FIRING_POLICY_EVERY_N:
- if (trigger->firing_policy.current_count < trigger->firing_policy.threshold) {
- ready_to_fire = true;
- }
- break;
- case LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N:
- if (trigger->firing_policy.current_count < trigger->firing_policy.threshold) {
- ready_to_fire = true;
- }
- break;
- default:
- abort();
- };
-
- return ready_to_fire;
-}
-
-LTTNG_HIDDEN
-void lttng_trigger_fire(struct lttng_trigger *trigger)
-{
- assert(trigger);
-
- trigger->firing_policy.current_count++;
-
- switch (trigger->firing_policy.type) {
- case LTTNG_TRIGGER_FIRING_POLICY_EVERY_N:
- if (trigger->firing_policy.current_count == trigger->firing_policy.threshold) {
- trigger->firing_policy.current_count = 0;
- }
-
- break;
- case LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N:
- /*
- * TODO:
- * As an optimisation, deactivate the trigger condition and
- * remove any checks in the traced application or kernel since
- * the trigger will never fire again.
- */
- break;
- default:
- abort();
- };
-}
-
LTTNG_HIDDEN
enum lttng_domain_type lttng_trigger_get_underlying_domain_type_restriction(
const struct lttng_trigger *trigger)
end:
return needs_tracer_notifier;
}
+
+LTTNG_HIDDEN
+void lttng_trigger_set_as_registered(struct lttng_trigger *trigger)
+{
+ pthread_mutex_lock(&trigger->lock);
+ trigger->registered = true;
+ pthread_mutex_unlock(&trigger->lock);
+}
+
+LTTNG_HIDDEN
+void lttng_trigger_set_as_unregistered(struct lttng_trigger *trigger)
+{
+ pthread_mutex_lock(&trigger->lock);
+ trigger->registered = false;
+ pthread_mutex_unlock(&trigger->lock);
+}
+
+/*
+ * The trigger must be locked before calling lttng_trigger_registered.
+ * The lock is necessary since a trigger can be unregistered at anytime.
+ * Manipulations requiring that the trigger be registered must always acquire
+ * the trigger lock for the duration of the manipulation using
+ * `lttng_trigger_lock` and `lttng_trigger_unlock`.
+ */
+LTTNG_HIDDEN
+bool lttng_trigger_is_registered(struct lttng_trigger *trigger)
+{
+ ASSERT_LOCKED(trigger->lock);
+ return trigger->registered;
+}
+
+LTTNG_HIDDEN
+void lttng_trigger_lock(struct lttng_trigger *trigger)
+{
+ pthread_mutex_lock(&trigger->lock);
+}
+
+LTTNG_HIDDEN
+void lttng_trigger_unlock(struct lttng_trigger *trigger)
+{
+ pthread_mutex_unlock(&trigger->lock);
+}