From 1120fb256441159b46f6bfc0c89f5b3a8857a572 Mon Sep 17 00:00:00 2001 From: Jason Dellaluce Date: Tue, 21 Jun 2022 17:06:39 +0000 Subject: [PATCH] doc(userspace/engine): define thread-safety guarantees of falco_engine::process_event Signed-off-by: Jason Dellaluce --- userspace/engine/falco_engine.cpp | 6 ++++++ userspace/engine/falco_engine.h | 31 +++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/userspace/engine/falco_engine.cpp b/userspace/engine/falco_engine.cpp index 35f99d97..fda242b7 100644 --- a/userspace/engine/falco_engine.cpp +++ b/userspace/engine/falco_engine.cpp @@ -332,6 +332,12 @@ std::shared_ptr falco_engine::create_formatter(const std::s unique_ptr falco_engine::process_event(std::size_t source_idx, gen_event *ev, uint16_t ruleset_id) { falco_rule rule; + + // note: there are no thread-safety guarantees on the filter_ruleset::run() + // method, but the thread-safety assumptions of falco_engine::process_event() + // imply that concurrent invokers use different and non-switchable values of + // source_idx, which means that at any time each filter_ruleset will only + // be accessed by a single thread. if(should_drop_evt() || !find_source(source_idx)->ruleset->run(ev, rule, ruleset_id)) { return unique_ptr(); diff --git a/userspace/engine/falco_engine.h b/userspace/engine/falco_engine.h index 7a6cf948..dcd492a6 100644 --- a/userspace/engine/falco_engine.h +++ b/userspace/engine/falco_engine.h @@ -165,18 +165,33 @@ public: // // Given an event, check it against the set of rules in the // engine and if a matching rule is found, return details on - // the rule that matched. If no rule matched, returns NULL. + // the rule that matched. If no rule matched, returns nullptr. // - // When ruleset_id is provided, use the enabled/disabled status - // associated with the provided ruleset. This is only useful - // when you have previously called enable_rule/enable_rule_by_tag - // with a ruleset string. - // - // the returned rule_result is allocated and must be delete()d. + // This method should be invoked only after having initialized and + // configured the engine. In particular, invoking this with a source_idx + // not previosly-returned by a call to add_source() would cause a + // falco_exception to be thrown. + // + // This method is thread-safe only with the assumption that every invoker + // uses a different source_idx. Moreover, each invoker must not switch + // source_idx in subsequent invokations of this method. + // Considering that each invoker is related to a unique event source, it + // is safe to assume that each invoker will pass a different event + // to this method too, since two distinct sources cannot possibly produce + // the same event. Lastly, filterchecks and formatters (and their factories) + // that used to populate the conditions for a given event-source ruleset, + // must not be reused across rulesets of other event sources. + // These assumptions guarantee thread-safety because internally the engine + // is partitioned by event sources. However, each ruleset assigned to each + // event source is not thread-safe of its own, so invoking this method + // concurrently with the same source_idx would inherently cause data races + // and lead to undefined behavior. std::unique_ptr process_event(std::size_t source_idx, gen_event *ev, uint16_t ruleset_id); // - // Wrapper assuming the default ruleset + // Wrapper assuming the default ruleset. + // + // This inherits the same thread-safety guarantees. // std::unique_ptr process_event(std::size_t source_idx, gen_event *ev);