mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
Reformat the world
This commit is contained in:
parent
194cb24547
commit
b2f171ec69
714 changed files with 35149 additions and 35203 deletions
|
@ -1,41 +1,42 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "zeek/zeek-config.h"
|
||||
#include "zeek/supervisor/Supervisor.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <csignal>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
#include "zeek/zeek-config.h"
|
||||
|
||||
#define RAPIDJSON_HAS_STDSTRING 1
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#include "zeek/setsignal.h"
|
||||
}
|
||||
}
|
||||
|
||||
#include "zeek/iosource/Manager.h"
|
||||
#include "zeek/ZeekString.h"
|
||||
#include "zeek/DebugLogger.h"
|
||||
#include "zeek/Dict.h"
|
||||
#include "zeek/ID.h"
|
||||
#include "zeek/NetVar.h"
|
||||
#include "zeek/RE.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Scope.h"
|
||||
#include "zeek/DebugLogger.h"
|
||||
#include "zeek/ID.h"
|
||||
#include "zeek/Val.h"
|
||||
#include "zeek/RunState.h"
|
||||
#include "zeek/NetVar.h"
|
||||
#include "zeek/util.h"
|
||||
#include "zeek/Scope.h"
|
||||
#include "zeek/Val.h"
|
||||
#include "zeek/ZeekString.h"
|
||||
#include "zeek/input.h"
|
||||
#include "zeek/iosource/Manager.h"
|
||||
#include "zeek/util.h"
|
||||
#include "zeek/zeek-affinity.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -51,22 +52,25 @@ using zeek::detail::SupervisorStemHandle;
|
|||
|
||||
std::optional<SupervisedNode> Supervisor::supervised_node;
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
|
||||
struct Stem {
|
||||
struct Stem
|
||||
{
|
||||
/**
|
||||
* State used to initalialize the Stem process.
|
||||
*/
|
||||
struct State {
|
||||
* State used to initalialize the Stem process.
|
||||
*/
|
||||
struct State
|
||||
{
|
||||
/**
|
||||
* Bidirectional pipes that allow the Supervisor and Stem to talk.
|
||||
*/
|
||||
* Bidirectional pipes that allow the Supervisor and Stem to talk.
|
||||
*/
|
||||
std::unique_ptr<detail::PipePair> pipe;
|
||||
/**
|
||||
* The Stem's parent process ID (i.e. PID of the Supervisor).
|
||||
*/
|
||||
* The Stem's parent process ID (i.e. PID of the Supervisor).
|
||||
*/
|
||||
pid_t parent_pid = 0;
|
||||
};
|
||||
};
|
||||
|
||||
Stem(State stem_state);
|
||||
|
||||
|
@ -116,8 +120,8 @@ struct Stem {
|
|||
std::map<std::string, SupervisorNode> nodes;
|
||||
std::string msg_buffer;
|
||||
bool shutting_down = false;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static Stem* stem = nullptr;
|
||||
|
||||
|
@ -146,7 +150,7 @@ static std::vector<std::string> extract_msgs(std::string* buffer, char delim)
|
|||
{
|
||||
std::vector<std::string> rval;
|
||||
|
||||
for ( ; ; )
|
||||
for ( ;; )
|
||||
{
|
||||
auto msg_end = buffer->find(delim);
|
||||
|
||||
|
@ -162,8 +166,7 @@ static std::vector<std::string> extract_msgs(std::string* buffer, char delim)
|
|||
return rval;
|
||||
}
|
||||
|
||||
static std::pair<int, std::vector<std::string>>
|
||||
read_msgs(int fd, std::string* buffer, char delim)
|
||||
static std::pair<int, std::vector<std::string>> read_msgs(int fd, std::string* buffer, char delim)
|
||||
{
|
||||
constexpr auto buf_size = 256;
|
||||
char buf[buf_size];
|
||||
|
@ -183,8 +186,7 @@ static std::string make_create_message(const Supervisor::NodeConfig& node)
|
|||
return util::fmt("create %s %s", node.name.data(), json_str.data());
|
||||
}
|
||||
|
||||
detail::ParentProcessCheckTimer::ParentProcessCheckTimer(double t,
|
||||
double arg_interval)
|
||||
detail::ParentProcessCheckTimer::ParentProcessCheckTimer(double t, double arg_interval)
|
||||
: Timer(t, TIMER_PPID_CHECK), interval(arg_interval)
|
||||
{
|
||||
}
|
||||
|
@ -203,8 +205,7 @@ void detail::ParentProcessCheckTimer::Dispatch(double t, bool is_expire)
|
|||
run_state::detail::zeek_terminate_loop("supervised node was orphaned");
|
||||
|
||||
if ( ! is_expire )
|
||||
timer_mgr->Add(new ParentProcessCheckTimer(run_state::network_time + interval,
|
||||
interval));
|
||||
timer_mgr->Add(new ParentProcessCheckTimer(run_state::network_time + interval, interval));
|
||||
}
|
||||
|
||||
Supervisor::Supervisor(Supervisor::Config cfg, SupervisorStemHandle sh)
|
||||
|
@ -228,16 +229,13 @@ Supervisor::Supervisor(Supervisor::Config cfg, SupervisorStemHandle sh)
|
|||
return;
|
||||
|
||||
if ( res == -1 )
|
||||
fprintf(stderr, "Supervisor failed to get status of stem process: %s\n",
|
||||
strerror(errno));
|
||||
fprintf(stderr, "Supervisor failed to get status of stem process: %s\n", strerror(errno));
|
||||
else
|
||||
{
|
||||
if ( WIFEXITED(status) )
|
||||
fprintf(stderr, "Supervisor stem died early with exit code %d\n",
|
||||
WEXITSTATUS(status));
|
||||
fprintf(stderr, "Supervisor stem died early with exit code %d\n", WEXITSTATUS(status));
|
||||
else if ( WIFSIGNALED(status) )
|
||||
fprintf(stderr, "Supervisor stem died early by signal %d\n",
|
||||
WTERMSIG(status));
|
||||
fprintf(stderr, "Supervisor stem died early by signal %d\n", WTERMSIG(status));
|
||||
else
|
||||
fprintf(stderr, "Supervisor stem died early for unknown reason\n");
|
||||
}
|
||||
|
@ -284,7 +282,8 @@ Supervisor::~Supervisor()
|
|||
stem_stdout.Drain();
|
||||
stem_stderr.Drain();
|
||||
|
||||
while ( ProcessMessages() != 0 );
|
||||
while ( ProcessMessages() != 0 )
|
||||
;
|
||||
}
|
||||
|
||||
void Supervisor::ObserveChildSignal(int signo)
|
||||
|
@ -310,7 +309,8 @@ void Supervisor::ReapStem()
|
|||
char tmp[256];
|
||||
util::zeek_strerror_r(errno, tmp, sizeof(tmp));
|
||||
reporter->Error("Supervisor failed to get exit status"
|
||||
" of stem process: %s", tmp);
|
||||
" of stem process: %s",
|
||||
tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -318,31 +318,28 @@ void Supervisor::ReapStem()
|
|||
|
||||
if ( WIFEXITED(status) )
|
||||
{
|
||||
DBG_LOG(DBG_SUPERVISOR, "stem process exited with status %d",
|
||||
WEXITSTATUS(status));
|
||||
DBG_LOG(DBG_SUPERVISOR, "stem process exited with status %d", WEXITSTATUS(status));
|
||||
}
|
||||
else if ( WIFSIGNALED(status) )
|
||||
{
|
||||
DBG_LOG(DBG_SUPERVISOR, "stem process terminated by signal %d",
|
||||
WTERMSIG(status));
|
||||
DBG_LOG(DBG_SUPERVISOR, "stem process terminated by signal %d", WTERMSIG(status));
|
||||
}
|
||||
else
|
||||
reporter->Error("Supervisor failed to get exit status"
|
||||
" of stem process for unknown reason");
|
||||
}
|
||||
|
||||
struct ForkResult {
|
||||
struct ForkResult
|
||||
{
|
||||
pid_t pid;
|
||||
std::unique_ptr<detail::Pipe> stdout_pipe;
|
||||
std::unique_ptr<detail::Pipe> stderr_pipe;
|
||||
};
|
||||
};
|
||||
|
||||
static ForkResult fork_with_stdio_redirect(const char* where)
|
||||
{
|
||||
auto out = std::make_unique<detail::Pipe>(FD_CLOEXEC, FD_CLOEXEC,
|
||||
O_NONBLOCK, O_NONBLOCK);
|
||||
auto err = std::make_unique<detail::Pipe>(FD_CLOEXEC, FD_CLOEXEC,
|
||||
O_NONBLOCK, O_NONBLOCK);
|
||||
auto out = std::make_unique<detail::Pipe>(FD_CLOEXEC, FD_CLOEXEC, O_NONBLOCK, O_NONBLOCK);
|
||||
auto err = std::make_unique<detail::Pipe>(FD_CLOEXEC, FD_CLOEXEC, O_NONBLOCK, O_NONBLOCK);
|
||||
auto pid = fork();
|
||||
|
||||
if ( pid == 0 )
|
||||
|
@ -352,9 +349,8 @@ static ForkResult fork_with_stdio_redirect(const char* where)
|
|||
if ( errno == EINTR )
|
||||
continue;
|
||||
|
||||
fprintf(stderr,
|
||||
"Supervisor %s fork() stdout redirect failed: %s\n",
|
||||
where, strerror(errno));
|
||||
fprintf(stderr, "Supervisor %s fork() stdout redirect failed: %s\n", where,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
while ( dup2(err->WriteFD(), STDERR_FILENO) == -1 )
|
||||
|
@ -362,9 +358,8 @@ static ForkResult fork_with_stdio_redirect(const char* where)
|
|||
if ( errno == EINTR )
|
||||
continue;
|
||||
|
||||
fprintf(stderr,
|
||||
"Supervisor %s fork() stderr redirect failed: %s\n",
|
||||
where, strerror(errno));
|
||||
fprintf(stderr, "Supervisor %s fork() stderr redirect failed: %s\n", where,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
// Default buffering for stdout may be fully-buffered if not a TTY,
|
||||
|
@ -421,14 +416,13 @@ void Supervisor::HandleChildSignal()
|
|||
if ( stem_pid == 0 )
|
||||
{
|
||||
// Child stem process needs to exec()
|
||||
auto stem_env = util::fmt("%d,%d,%d,%d,%d", stem_ppid,
|
||||
stem_pipe->In().ReadFD(), stem_pipe->In().WriteFD(),
|
||||
stem_pipe->Out().ReadFD(), stem_pipe->Out().WriteFD());
|
||||
auto stem_env = util::fmt("%d,%d,%d,%d,%d", stem_ppid, stem_pipe->In().ReadFD(),
|
||||
stem_pipe->In().WriteFD(), stem_pipe->Out().ReadFD(),
|
||||
stem_pipe->Out().WriteFD());
|
||||
|
||||
if ( setenv("ZEEK_STEM", stem_env, true) == -1 )
|
||||
{
|
||||
fprintf(stderr, "setenv(ZEEK_STEM) failed: %s\n",
|
||||
strerror(errno));
|
||||
fprintf(stderr, "setenv(ZEEK_STEM) failed: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -443,19 +437,18 @@ void Supervisor::HandleChildSignal()
|
|||
args[i] = detail::zeek_argv[i];
|
||||
|
||||
auto res = execv(config.zeek_exe_path.data(), args);
|
||||
fprintf(stderr, "failed to exec Zeek supervisor stem process: %s\n",
|
||||
strerror(errno));
|
||||
fprintf(stderr, "failed to exec Zeek supervisor stem process: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ! iosource_mgr->UnregisterFd(stem_stdout.pipe->ReadFD(), this) )
|
||||
reporter->FatalError("Revived supervisor stem failed to unregister "
|
||||
"redirected stdout pipe");
|
||||
"redirected stdout pipe");
|
||||
|
||||
if ( ! iosource_mgr->UnregisterFd(stem_stderr.pipe->ReadFD(), this) )
|
||||
reporter->FatalError("Revived supervisor stem failed to unregister "
|
||||
"redirected stderr pipe");
|
||||
"redirected stderr pipe");
|
||||
|
||||
stem_stdout.Drain();
|
||||
stem_stderr.Drain();
|
||||
|
@ -464,11 +457,11 @@ void Supervisor::HandleChildSignal()
|
|||
|
||||
if ( ! iosource_mgr->RegisterFd(stem_stdout.pipe->ReadFD(), this) )
|
||||
reporter->FatalError("Revived supervisor stem failed to register "
|
||||
"redirected stdout pipe");
|
||||
"redirected stdout pipe");
|
||||
|
||||
if ( ! iosource_mgr->RegisterFd(stem_stderr.pipe->ReadFD(), this) )
|
||||
reporter->FatalError("Revived supervisor stem failed to register "
|
||||
"redirected stderr pipe");
|
||||
"redirected stderr pipe");
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_SUPERVISOR, "stem process revived, new pid: %d", stem_pid);
|
||||
|
@ -551,8 +544,8 @@ void zeek::detail::LineBufferedPipe::Emit(const char* msg) const
|
|||
}
|
||||
}
|
||||
|
||||
auto res = hook->Invoke(make_intrusive<StringVal>(node_len, node),
|
||||
make_intrusive<StringVal>(msg));
|
||||
auto res =
|
||||
hook->Invoke(make_intrusive<StringVal>(node_len, node), make_intrusive<StringVal>(msg));
|
||||
do_print = res->AsBool();
|
||||
}
|
||||
|
||||
|
@ -562,7 +555,8 @@ void zeek::detail::LineBufferedPipe::Emit(const char* msg) const
|
|||
|
||||
void zeek::detail::LineBufferedPipe::Drain()
|
||||
{
|
||||
while ( Process() != 0 );
|
||||
while ( Process() != 0 )
|
||||
;
|
||||
|
||||
Emit(buffer.data());
|
||||
buffer.clear();
|
||||
|
@ -683,16 +677,16 @@ bool Stem::Wait(SupervisorNode* node, int options) const
|
|||
|
||||
if ( res == -1 )
|
||||
{
|
||||
LogError("Stem failed to get node exit status '%s' (PID %d): %s",
|
||||
node->Name().data(), node->pid, strerror(errno));
|
||||
LogError("Stem failed to get node exit status '%s' (PID %d): %s", node->Name().data(),
|
||||
node->pid, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( WIFEXITED(status) )
|
||||
{
|
||||
node->exit_status = WEXITSTATUS(status);
|
||||
DBG_STEM("node '%s' (PID %d) exited with status %d",
|
||||
node->Name().data(), node->pid, node->exit_status);
|
||||
DBG_STEM("node '%s' (PID %d) exited with status %d", node->Name().data(), node->pid,
|
||||
node->exit_status);
|
||||
|
||||
if ( ! node->killed )
|
||||
LogError("Supervised node '%s' (PID %d) exited prematurely with status %d",
|
||||
|
@ -701,16 +695,16 @@ bool Stem::Wait(SupervisorNode* node, int options) const
|
|||
else if ( WIFSIGNALED(status) )
|
||||
{
|
||||
node->signal_number = WTERMSIG(status);
|
||||
DBG_STEM("node '%s' (PID %d) terminated by signal %d",
|
||||
node->Name().data(), node->pid, node->signal_number);
|
||||
DBG_STEM("node '%s' (PID %d) terminated by signal %d", node->Name().data(), node->pid,
|
||||
node->signal_number);
|
||||
|
||||
if ( ! node->killed )
|
||||
LogError("Supervised node '%s' (PID %d) terminated prematurely by signal %d",
|
||||
node->Name().data(), node->pid, node->signal_number);
|
||||
}
|
||||
else
|
||||
LogError("Stem failed to get node exit status '%s' (PID %d)",
|
||||
node->Name().data(), node->pid);
|
||||
LogError("Stem failed to get node exit status '%s' (PID %d)", node->Name().data(),
|
||||
node->pid);
|
||||
|
||||
node->pid = 0;
|
||||
node->stdout_pipe.Drain();
|
||||
|
@ -722,8 +716,8 @@ void Stem::KillNode(SupervisorNode* node, int signal) const
|
|||
{
|
||||
if ( node->pid <= 0 )
|
||||
{
|
||||
DBG_STEM("Stem skip killing node '%s' (PID %d): already dead",
|
||||
node->Name().data(), node->pid);
|
||||
DBG_STEM("Stem skip killing node '%s' (PID %d): already dead", node->Name().data(),
|
||||
node->pid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -731,8 +725,8 @@ void Stem::KillNode(SupervisorNode* node, int signal) const
|
|||
auto kill_res = kill(node->pid, signal);
|
||||
|
||||
if ( kill_res == -1 )
|
||||
LogError("Failed to send signal to node '%s' (PID %d): %s",
|
||||
node->Name().data(), node->pid, strerror(errno));
|
||||
LogError("Failed to send signal to node '%s' (PID %d): %s", node->Name().data(), node->pid,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
static int get_kill_signal(int attempts, int max_attempts)
|
||||
|
@ -754,12 +748,12 @@ void Stem::Destroy(SupervisorNode* node) const
|
|||
|
||||
if ( node->pid <= 0 )
|
||||
{
|
||||
DBG_STEM("Stem skip killing/waiting node '%s' (PID %d): already dead",
|
||||
node->Name().data(), node->pid);
|
||||
DBG_STEM("Stem skip killing/waiting node '%s' (PID %d): already dead", node->Name().data(),
|
||||
node->pid);
|
||||
return;
|
||||
}
|
||||
|
||||
for ( ; ; )
|
||||
for ( ;; )
|
||||
{
|
||||
auto sig = get_kill_signal(kill_attempts++, max_term_attempts);
|
||||
KillNode(node, sig);
|
||||
|
@ -770,8 +764,7 @@ void Stem::Destroy(SupervisorNode* node) const
|
|||
break;
|
||||
}
|
||||
|
||||
DBG_STEM("Stem waiting to destroy node: %s (PID %d)",
|
||||
node->Name().data(), node->pid);
|
||||
DBG_STEM("Stem waiting to destroy node: %s (PID %d)", node->Name().data(), node->pid);
|
||||
sleep(kill_delay);
|
||||
}
|
||||
}
|
||||
|
@ -817,7 +810,7 @@ std::optional<SupervisedNode> Stem::Revive()
|
|||
|
||||
if ( std::get<bool>(spawn_res) )
|
||||
LogError("Supervised node '%s' (PID %d) revived after premature exit",
|
||||
node.Name().data(), node.pid);
|
||||
node.Name().data(), node.pid);
|
||||
|
||||
ReportStatus(node);
|
||||
}
|
||||
|
@ -833,8 +826,7 @@ std::variant<bool, SupervisedNode> Stem::Spawn(SupervisorNode* node)
|
|||
|
||||
if ( node_pid == -1 )
|
||||
{
|
||||
LogError("failed to fork Zeek node '%s': %s",
|
||||
node->Name().data(), strerror(errno));
|
||||
LogError("failed to fork Zeek node '%s': %s", node->Name().data(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -887,7 +879,7 @@ void Stem::Shutdown(int exit_code)
|
|||
constexpr auto kill_delay = 2;
|
||||
auto kill_attempts = 0;
|
||||
|
||||
for ( ; ; )
|
||||
for ( ;; )
|
||||
{
|
||||
auto sig = get_kill_signal(kill_attempts++, max_term_attempts);
|
||||
|
||||
|
@ -906,8 +898,7 @@ void Stem::Shutdown(int exit_code)
|
|||
exit(exit_code);
|
||||
}
|
||||
|
||||
DBG_STEM("Stem nodes still alive %d, sleeping for %d seconds",
|
||||
nodes_alive, kill_delay);
|
||||
DBG_STEM("Stem nodes still alive %d, sleeping for %d seconds", nodes_alive, kill_delay);
|
||||
|
||||
auto sleep_time_left = kill_delay;
|
||||
|
||||
|
@ -969,7 +960,7 @@ void Stem::LogError(const char* format, ...) const
|
|||
|
||||
SupervisedNode Stem::Run()
|
||||
{
|
||||
for ( ; ; )
|
||||
for ( ;; )
|
||||
{
|
||||
auto new_node = Poll();
|
||||
|
||||
|
@ -989,22 +980,22 @@ std::optional<SupervisedNode> Stem::Poll()
|
|||
const auto total_fd_count = fixed_fd_count + (nodes.size() * 2);
|
||||
auto pfds = std::make_unique<pollfd[]>(total_fd_count);
|
||||
int pfd_idx = 0;
|
||||
pfds[pfd_idx++] = { pipe->InFD(), POLLIN, 0 };
|
||||
pfds[pfd_idx++] = { signal_flare->FD(), POLLIN, 0 };
|
||||
pfds[pfd_idx++] = {pipe->InFD(), POLLIN, 0};
|
||||
pfds[pfd_idx++] = {signal_flare->FD(), POLLIN, 0};
|
||||
|
||||
for ( const auto& [name, node] : nodes )
|
||||
{
|
||||
node_pollfd_indices[name] = pfd_idx;
|
||||
|
||||
if ( node.stdout_pipe.pipe )
|
||||
pfds[pfd_idx++] = { node.stdout_pipe.pipe->ReadFD(), POLLIN, 0 };
|
||||
pfds[pfd_idx++] = {node.stdout_pipe.pipe->ReadFD(), POLLIN, 0};
|
||||
else
|
||||
pfds[pfd_idx++] = { -1, POLLIN, 0 };
|
||||
pfds[pfd_idx++] = {-1, POLLIN, 0};
|
||||
|
||||
if ( node.stderr_pipe.pipe )
|
||||
pfds[pfd_idx++] = { node.stderr_pipe.pipe->ReadFD(), POLLIN, 0 };
|
||||
pfds[pfd_idx++] = {node.stderr_pipe.pipe->ReadFD(), POLLIN, 0};
|
||||
else
|
||||
pfds[pfd_idx++] = { -1, POLLIN, 0 };
|
||||
pfds[pfd_idx++] = {-1, POLLIN, 0};
|
||||
}
|
||||
|
||||
// Note: the poll timeout here is for periodically checking if the parent
|
||||
|
@ -1161,8 +1152,7 @@ std::optional<SupervisorStemHandle> Supervisor::CreateStem(bool supervisor_mode)
|
|||
|
||||
if ( zeek_stem_nums.size() != 5 )
|
||||
{
|
||||
fprintf(stderr, "invalid ZEEK_STEM environment variable value: '%s'\n",
|
||||
zeek_stem_env);
|
||||
fprintf(stderr, "invalid ZEEK_STEM environment variable value: '%s'\n", zeek_stem_env);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -1192,8 +1182,7 @@ std::optional<SupervisorStemHandle> Supervisor::CreateStem(bool supervisor_mode)
|
|||
|
||||
if ( pid == -1 )
|
||||
{
|
||||
fprintf(stderr, "failed to fork Zeek supervisor stem process: %s\n",
|
||||
strerror(errno));
|
||||
fprintf(stderr, "failed to fork Zeek supervisor stem process: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -1325,10 +1314,10 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromJSON(std::string_view json)
|
|||
rval.directory = it->value.GetString();
|
||||
|
||||
if ( auto it = j.FindMember("stdout_file"); it != j.MemberEnd() )
|
||||
rval.stdout_file= it->value.GetString();
|
||||
rval.stdout_file = it->value.GetString();
|
||||
|
||||
if ( auto it = j.FindMember("stderr_file"); it != j.MemberEnd() )
|
||||
rval.stderr_file= it->value.GetString();
|
||||
rval.stderr_file = it->value.GetString();
|
||||
|
||||
if ( auto it = j.FindMember("cpu_affinity"); it != j.MemberEnd() )
|
||||
rval.cpu_affinity = it->value.GetInt();
|
||||
|
@ -1457,23 +1446,23 @@ RecordValPtr SupervisorNode::ToRecord() const
|
|||
return rval;
|
||||
}
|
||||
|
||||
|
||||
static ValPtr supervisor_role_to_cluster_node_type(BifEnum::Supervisor::ClusterRole role)
|
||||
{
|
||||
static auto node_type = id::find_type<zeek::EnumType>("Cluster::NodeType");
|
||||
|
||||
switch ( role ) {
|
||||
case BifEnum::Supervisor::LOGGER:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "LOGGER"));
|
||||
case BifEnum::Supervisor::MANAGER:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "MANAGER"));
|
||||
case BifEnum::Supervisor::PROXY:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "PROXY"));
|
||||
case BifEnum::Supervisor::WORKER:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "WORKER"));
|
||||
default:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "NONE"));
|
||||
}
|
||||
switch ( role )
|
||||
{
|
||||
case BifEnum::Supervisor::LOGGER:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "LOGGER"));
|
||||
case BifEnum::Supervisor::MANAGER:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "MANAGER"));
|
||||
case BifEnum::Supervisor::PROXY:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "PROXY"));
|
||||
case BifEnum::Supervisor::WORKER:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "WORKER"));
|
||||
default:
|
||||
return node_type->GetEnumVal(node_type->Lookup("Cluster", "NONE"));
|
||||
}
|
||||
}
|
||||
|
||||
bool SupervisedNode::InitCluster() const
|
||||
|
@ -1530,9 +1519,8 @@ void SupervisedNode::Init(Options* options) const
|
|||
{
|
||||
if ( chdir(config.directory->data()) )
|
||||
{
|
||||
fprintf(stderr, "node '%s' failed to chdir to %s: %s\n",
|
||||
node_name.data(), config.directory->data(),
|
||||
strerror(errno));
|
||||
fprintf(stderr, "node '%s' failed to chdir to %s: %s\n", node_name.data(),
|
||||
config.directory->data(), strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -1540,14 +1528,12 @@ void SupervisedNode::Init(Options* options) const
|
|||
if ( config.stderr_file )
|
||||
{
|
||||
auto fd = open(config.stderr_file->data(),
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_APPEND | O_CLOEXEC,
|
||||
0600);
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_APPEND | O_CLOEXEC, 0600);
|
||||
|
||||
if ( fd == -1 || dup2(fd, STDERR_FILENO) == -1 )
|
||||
{
|
||||
fprintf(stderr, "node '%s' failed to create stderr file %s: %s\n",
|
||||
node_name.data(), config.stderr_file->data(),
|
||||
strerror(errno));
|
||||
fprintf(stderr, "node '%s' failed to create stderr file %s: %s\n", node_name.data(),
|
||||
config.stderr_file->data(), strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -1557,14 +1543,12 @@ void SupervisedNode::Init(Options* options) const
|
|||
if ( config.stdout_file )
|
||||
{
|
||||
auto fd = open(config.stdout_file->data(),
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_APPEND | O_CLOEXEC,
|
||||
0600);
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_APPEND | O_CLOEXEC, 0600);
|
||||
|
||||
if ( fd == -1 || dup2(fd, STDOUT_FILENO) == -1 )
|
||||
{
|
||||
fprintf(stderr, "node '%s' failed to create stdout file %s: %s\n",
|
||||
node_name.data(), config.stdout_file->data(),
|
||||
strerror(errno));
|
||||
fprintf(stderr, "node '%s' failed to create stdout file %s: %s\n", node_name.data(),
|
||||
config.stdout_file->data(), strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -1576,8 +1560,8 @@ void SupervisedNode::Init(Options* options) const
|
|||
auto res = set_affinity(*config.cpu_affinity);
|
||||
|
||||
if ( ! res )
|
||||
fprintf(stderr, "node '%s' failed to set CPU affinity: %s\n",
|
||||
node_name.data(), strerror(errno));
|
||||
fprintf(stderr, "node '%s' failed to set CPU affinity: %s\n", node_name.data(),
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
if ( ! config.env.empty() )
|
||||
|
@ -1586,8 +1570,8 @@ void SupervisedNode::Init(Options* options) const
|
|||
{
|
||||
if ( setenv(e.first.c_str(), e.second.c_str(), true) == -1 )
|
||||
{
|
||||
fprintf(stderr, "node '%s' failed to setenv: %s\n",
|
||||
node_name.data(), strerror(errno));
|
||||
fprintf(stderr, "node '%s' failed to setenv: %s\n", node_name.data(),
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -1597,8 +1581,7 @@ void SupervisedNode::Init(Options* options) const
|
|||
{
|
||||
if ( setenv("CLUSTER_NODE", node_name.data(), true) == -1 )
|
||||
{
|
||||
fprintf(stderr, "node '%s' failed to setenv: %s\n",
|
||||
node_name.data(), strerror(errno));
|
||||
fprintf(stderr, "node '%s' failed to setenv: %s\n", node_name.data(), strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -1662,8 +1645,7 @@ std::string Supervisor::Create(const Supervisor::NodeConfig& node)
|
|||
return "node names must not be an empty string";
|
||||
|
||||
if ( node.name.find(' ') != std::string::npos )
|
||||
return util::fmt("node names must not contain spaces: '%s'",
|
||||
node.name.data());
|
||||
return util::fmt("node names must not contain spaces: '%s'", node.name.data());
|
||||
|
||||
if ( nodes.find(node.name) != nodes.end() )
|
||||
return util::fmt("node with name '%s' already exists", node.name.data());
|
||||
|
@ -1673,8 +1655,7 @@ std::string Supervisor::Create(const Supervisor::NodeConfig& node)
|
|||
auto res = util::detail::ensure_intermediate_dirs(node.directory->data());
|
||||
|
||||
if ( ! res )
|
||||
return util::fmt("failed to create working directory %s\n",
|
||||
node.directory->data());
|
||||
return util::fmt("failed to create working directory %s\n", node.directory->data());
|
||||
}
|
||||
|
||||
auto msg = make_create_message(node);
|
||||
|
@ -1686,12 +1667,12 @@ std::string Supervisor::Create(const Supervisor::NodeConfig& node)
|
|||
bool Supervisor::Destroy(std::string_view node_name)
|
||||
{
|
||||
auto send_destroy_msg = [this](std::string_view name)
|
||||
{
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "destroy " << name;
|
||||
std::string msg = ss.str();
|
||||
util::safe_write(stem_pipe->OutFD(), msg.data(), msg.size() + 1);
|
||||
};
|
||||
};
|
||||
|
||||
if ( node_name.empty() )
|
||||
{
|
||||
|
@ -1715,12 +1696,12 @@ bool Supervisor::Destroy(std::string_view node_name)
|
|||
bool Supervisor::Restart(std::string_view node_name)
|
||||
{
|
||||
auto send_restart_msg = [this](std::string_view name)
|
||||
{
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "restart " << name;
|
||||
std::string msg = ss.str();
|
||||
util::safe_write(stem_pipe->OutFD(), msg.data(), msg.size() + 1);
|
||||
};
|
||||
};
|
||||
|
||||
if ( node_name.empty() )
|
||||
{
|
||||
|
|
|
@ -3,27 +3,29 @@
|
|||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "zeek/iosource/IOSource.h"
|
||||
#include "zeek/Timer.h"
|
||||
#include "zeek/Pipe.h"
|
||||
#include "zeek/Flare.h"
|
||||
#include "zeek/Func.h"
|
||||
#include "zeek/NetVar.h"
|
||||
#include "zeek/IntrusivePtr.h"
|
||||
#include "zeek/NetVar.h"
|
||||
#include "zeek/Options.h"
|
||||
#include "zeek/Pipe.h"
|
||||
#include "zeek/Timer.h"
|
||||
#include "zeek/iosource/IOSource.h"
|
||||
|
||||
namespace zeek {
|
||||
namespace detail {
|
||||
namespace zeek
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct SupervisorStemHandle;
|
||||
struct SupervisedNode;
|
||||
|
@ -33,7 +35,8 @@ struct SupervisorNode;
|
|||
* A simple wrapper around a pipe to help do line-buffered output
|
||||
* of a Supervisor/Stem child process' redirected stdout/stderr.
|
||||
*/
|
||||
struct LineBufferedPipe {
|
||||
struct LineBufferedPipe
|
||||
{
|
||||
/**
|
||||
* A pipe that a parent process can read from to obtain output
|
||||
* written by a child process.
|
||||
|
@ -75,9 +78,9 @@ struct LineBufferedPipe {
|
|||
* A hook to call when emitting messages read from the pipe.
|
||||
*/
|
||||
FuncPtr hook;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
||||
/**
|
||||
* A Supervisor object manages a tree of persistent Zeek processes. If any
|
||||
|
@ -94,26 +97,28 @@ struct LineBufferedPipe {
|
|||
* will self-terminate if it detects its parent has died and that detection is
|
||||
* done via polling for change in parent process ID.
|
||||
*/
|
||||
class Supervisor : public iosource::IOSource {
|
||||
class Supervisor : public iosource::IOSource
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Configuration options that change Supervisor behavior.
|
||||
*/
|
||||
struct Config {
|
||||
struct Config
|
||||
{
|
||||
/**
|
||||
* The filesystem path of the Zeek binary/executable. This is used
|
||||
* if the Stem process ever dies and we need to fork() and exec() to
|
||||
* re-create it.
|
||||
*/
|
||||
std::string zeek_exe_path;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration options that influence how a Supervised Zeek node
|
||||
* integrates into the normal Zeek Cluster Framework.
|
||||
*/
|
||||
struct ClusterEndpoint {
|
||||
struct ClusterEndpoint
|
||||
{
|
||||
/**
|
||||
* The node's role within the cluster. E.g. manager, logger, worker.
|
||||
*/
|
||||
|
@ -131,12 +136,13 @@ public:
|
|||
* Typically used by worker nodes.
|
||||
*/
|
||||
std::optional<std::string> interface;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration options that influence behavior of a Supervised Zeek node.
|
||||
*/
|
||||
struct NodeConfig {
|
||||
struct NodeConfig
|
||||
{
|
||||
/**
|
||||
* Create configuration from script-layer record value.
|
||||
* @param node_val the script-layer record value to convert.
|
||||
|
@ -205,7 +211,7 @@ public:
|
|||
* Entries in the map use node names for keys.
|
||||
*/
|
||||
std::map<std::string, ClusterEndpoint> cluster;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create and run the Stem process if necessary.
|
||||
|
@ -223,8 +229,7 @@ public:
|
|||
* about itself if this is a supervised process. If called from a process
|
||||
* that is not supervised, this returns an "empty" object.
|
||||
*/
|
||||
static const std::optional<detail::SupervisedNode>& ThisNode()
|
||||
{ return supervised_node; }
|
||||
static const std::optional<detail::SupervisedNode>& ThisNode() { return supervised_node; }
|
||||
|
||||
using NodeMap = std::map<std::string, detail::SupervisorNode, std::less<>>;
|
||||
|
||||
|
@ -249,15 +254,13 @@ public:
|
|||
/**
|
||||
* @return the process ID of the Stem.
|
||||
*/
|
||||
pid_t StemPID() const
|
||||
{ return stem_pid; }
|
||||
pid_t StemPID() const { return stem_pid; }
|
||||
|
||||
/**
|
||||
* @return the state of currently supervised processes. The map uses
|
||||
* node names for keys.
|
||||
*/
|
||||
const NodeMap& Nodes()
|
||||
{ return nodes; }
|
||||
const NodeMap& Nodes() { return nodes; }
|
||||
|
||||
/**
|
||||
* Retrieve current status of a supervised node.
|
||||
|
@ -306,7 +309,6 @@ public:
|
|||
void ObserveChildSignal(int signo);
|
||||
|
||||
private:
|
||||
|
||||
// IOSource interface overrides:
|
||||
double GetNextTimeout() override;
|
||||
void Process() override;
|
||||
|
@ -317,8 +319,7 @@ private:
|
|||
|
||||
void ReapStem();
|
||||
|
||||
const char* Tag() override
|
||||
{ return "zeek::Supervisor"; }
|
||||
const char* Tag() override { return "zeek::Supervisor"; }
|
||||
|
||||
static std::optional<detail::SupervisedNode> supervised_node;
|
||||
|
||||
|
@ -331,13 +332,15 @@ private:
|
|||
detail::Flare signal_flare;
|
||||
NodeMap nodes;
|
||||
std::string msg_buffer;
|
||||
};
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* State used to initalialize and talk to the Supervisor Stem process.
|
||||
*/
|
||||
struct SupervisorStemHandle {
|
||||
struct SupervisorStemHandle
|
||||
{
|
||||
/**
|
||||
* Bidirectional pipes that allow the Supervisor and Stem to talk.
|
||||
*/
|
||||
|
@ -356,12 +359,13 @@ struct SupervisorStemHandle {
|
|||
* The Stem's process ID.
|
||||
*/
|
||||
pid_t pid = 0;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* State which defines a Supervised Zeek node's understanding of itself.
|
||||
*/
|
||||
struct SupervisedNode {
|
||||
struct SupervisedNode
|
||||
{
|
||||
/**
|
||||
* Initialize the Supervised node within the Zeek Cluster Framework.
|
||||
* This function populates the "Cluster::nodes" script-layer variable
|
||||
|
@ -389,12 +393,13 @@ struct SupervisedNode {
|
|||
* of the Stem process).
|
||||
*/
|
||||
pid_t parent_pid;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* The state of a supervised node from the Supervisor's perspective.
|
||||
*/
|
||||
struct SupervisorNode {
|
||||
struct SupervisorNode
|
||||
{
|
||||
/**
|
||||
* Convert the node into script-layer Supervisor::NodeStatus record
|
||||
* representation.
|
||||
|
@ -404,15 +409,13 @@ struct SupervisorNode {
|
|||
/**
|
||||
* @return the name of the node.
|
||||
*/
|
||||
const std::string& Name() const
|
||||
{ return config.name; }
|
||||
const std::string& Name() const { return config.name; }
|
||||
|
||||
/**
|
||||
* Create a new node state from a given configuration.
|
||||
* @param arg_config the configuration to use for the node.
|
||||
*/
|
||||
SupervisorNode(Supervisor::NodeConfig arg_config) : config(std::move(arg_config))
|
||||
{ }
|
||||
SupervisorNode(Supervisor::NodeConfig arg_config) : config(std::move(arg_config)) { }
|
||||
|
||||
/**
|
||||
* The desired configuration for the node.
|
||||
|
@ -458,16 +461,16 @@ struct SupervisorNode {
|
|||
* any output written to the Node's stdout.
|
||||
*/
|
||||
detail::LineBufferedPipe stderr_pipe;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* A timer used by supervised processes to periodically check whether their
|
||||
* parent (supervisor) process has died. If it has died, the supervised
|
||||
* process self-terminates.
|
||||
*/
|
||||
class ParentProcessCheckTimer final : public Timer {
|
||||
class ParentProcessCheckTimer final : public Timer
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create a timer to check for parent process death.
|
||||
* @param t the time at which to trigger the timer's check.
|
||||
|
@ -476,13 +479,12 @@ public:
|
|||
ParentProcessCheckTimer(double t, double interval);
|
||||
|
||||
protected:
|
||||
|
||||
void Dispatch(double t, bool is_expire) override;
|
||||
|
||||
double interval;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
extern Supervisor* supervisor_mgr;
|
||||
|
||||
} // namespace zeek
|
||||
} // namespace zeek
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue