From d8a082222197020b2ca02c5778837f14ef01e632 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Fri, 20 Oct 2023 16:36:13 +0200 Subject: [PATCH] event: Reinitialize EventMgr's flare after fork() from stem Because EventMgr is defined globally as an object (rather than a global pointer to an EventMgr object), its pipe is created even before main() is entered. This further means that in the fork-based supervisor setup, all Zeek processes created from the top-level supervisor process share the same pipe object for the EventMgr. In turn, whenever any of the processes enqueued an event, the flare was fired and ready for reading on all other processes in the cluster, causing much contention and unneeded overhead. Closes #3190 --- src/Event.cc | 8 ++++++++ src/Event.h | 3 +++ src/zeek-setup.cc | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/src/Event.cc b/src/Event.cc index de26955d56..f382163108 100644 --- a/src/Event.cc +++ b/src/Event.cc @@ -207,4 +207,12 @@ void EventMgr::InitPostScript() reporter->FatalError("Failed to register event manager FD with iosource_mgr"); } +void EventMgr::InitPostFork() + { + // Re-initialize the flare, closing and re-opening the underlying + // pipe FDs. This is needed so that each Zeek process in a supervisor + // setup has its own pipe instead of them all sharing a single pipe. + queue_flare = zeek::detail::Flare{}; + } + } // namespace zeek diff --git a/src/Event.h b/src/Event.h index b746635007..75929817c1 100644 --- a/src/Event.h +++ b/src/Event.h @@ -118,6 +118,9 @@ public: const char* Tag() override { return "EventManager"; } void InitPostScript(); + // Initialization to be done after a fork() happened. + void InitPostFork(); + uint64_t num_events_queued = 0; uint64_t num_events_dispatched = 0; diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index ed8455adea..4b4aabf42c 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -554,8 +554,14 @@ SetupResult setup(int argc, char** argv, Options* zopts) auto stem = Supervisor::CreateStem(options.supervisor_mode); if ( Supervisor::ThisNode() ) + { + // If we get here, we're a supervised node that just returned + // from CreateStem() after being forked from the stem. Supervisor::ThisNode()->Init(&options); + event_mgr.InitPostFork(); + } + script_coverage_mgr.ReadStats(); auto dns_type = options.dns_mode;