update(userspace/falco): improve falco termination

Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
This commit is contained in:
Andrea Terzolo 2022-05-23 17:34:48 +02:00 committed by poiana
parent 3a3d5dfdcd
commit d860472987
22 changed files with 109 additions and 198 deletions

View File

@ -51,6 +51,7 @@ static void restart_falco(int signal)
bool application::create_handler(int sig, void (*func)(int), run_result &ret)
{
ret = run_result::ok();
if(signal(sig, func) == SIG_ERR)
{
char errbuf[1024];
@ -59,13 +60,10 @@ bool application::create_handler(int sig, void (*func)(int), run_result &ret)
snprintf(errbuf, sizeof(errbuf)-1, "Errno %d", errno);
}
ret.success = false;
ret.errstr = std::string("Could not create signal handler for ") +
ret = run_result::fatal(std::string("Could not create signal handler for ") +
strsignal(sig) +
": " +
errbuf;
ret.proceed = false;
errbuf);
}
return ret.success;
@ -74,7 +72,6 @@ bool application::create_handler(int sig, void (*func)(int), run_result &ret)
application::run_result application::create_signal_handlers()
{
run_result ret;
if(! create_handler(SIGINT, ::signal_callback, ret) ||
! create_handler(SIGTERM, ::signal_callback, ret) ||
! create_handler(SIGUSR1, ::reopen_outputs, ret) ||
@ -84,22 +81,17 @@ application::run_result application::create_signal_handlers()
}
s_app = *this;
return ret;
}
application::run_result application::attach_inotify_signals()
{
run_result ret;
if (m_state->config->m_watch_config_files)
{
ret.proceed = false;
ret.success = false;
inot_fd = inotify_init();
if (inot_fd == -1)
{
ret.errstr = std::string("Could not create inotify handler.");
return ret;
return run_result::fatal("Could not create inotify handler.");
}
struct sigaction sa;
@ -108,15 +100,13 @@ application::run_result application::attach_inotify_signals()
sa.sa_handler = restart_falco;
if (sigaction(SIGIO, &sa, NULL) == -1)
{
ret.errstr = std::string("Failed to link SIGIO to inotify handler.");
return ret;
return run_result::fatal("Failed to link SIGIO to inotify handler.");
}
/* Set owner process that is to receive "I/O possible" signal */
if (fcntl(inot_fd, F_SETOWN, getpid()) == -1)
{
ret.errstr = std::string("Failed to setting owner on inotify handler.");
return ret;
return run_result::fatal("Failed to setting owner on inotify handler.");
}
/*
@ -126,16 +116,14 @@ application::run_result application::attach_inotify_signals()
int flags = fcntl(inot_fd, F_GETFL);
if (fcntl(inot_fd, F_SETFL, flags | O_ASYNC | O_NONBLOCK) == -1)
{
ret.errstr = std::string("Failed to setting flags on inotify handler.");
return ret;
return run_result::fatal("Failed to setting flags on inotify handler.");
}
// Watch conf file
int wd = inotify_add_watch(inot_fd, m_options.conf_filename.c_str(), IN_CLOSE_WRITE);
if (wd == -1)
{
ret.errstr = std::string("Failed to watch conf file.");
return ret;
return run_result::fatal("Failed to watch conf file.");
}
falco_logger::log(LOG_DEBUG, "Watching " + m_options.conf_filename +"\n");
@ -145,8 +133,7 @@ application::run_result application::attach_inotify_signals()
wd = inotify_add_watch(inot_fd, rule.c_str(), IN_CLOSE_WRITE | IN_ONESHOT);
if (wd == -1)
{
ret.errstr = std::string("Failed to watch rule file: ") + rule;
return ret;
return run_result::fatal("Failed to watch rule file: " + rule);
}
falco_logger::log(LOG_DEBUG, "Watching " + rule +".\n");
}
@ -160,24 +147,18 @@ application::run_result application::attach_inotify_signals()
wd = inotify_add_watch(inot_fd, fld.c_str(), IN_CREATE | IN_DELETE | IN_ONESHOT);
if (wd == -1)
{
ret.errstr = std::string("Failed to watch rule folder: ") + fld;
return ret;
return run_result::fatal("Failed to watch rule folder: " + fld);
}
falco_logger::log(LOG_DEBUG, "Watching " + fld +" folder.\n");
}
ret.success = true;
ret.proceed = true;
}
return ret;
return run_result::ok();
}
bool application::unregister_signal_handlers(std::string &errstr)
{
run_result ret;
close(inot_fd);
if(! create_handler(SIGINT, SIG_DFL, ret) ||
! create_handler(SIGTERM, SIG_DFL, ret) ||
! create_handler(SIGUSR1, SIG_DFL, ret) ||
@ -188,6 +169,5 @@ bool application::unregister_signal_handlers(std::string &errstr)
}
s_app = dummy;
return true;
}

View File

@ -26,8 +26,6 @@ static bool s_daemonized = false;
application::run_result application::daemonize()
{
run_result ret;
// If daemonizing, do it here so any init errors will
// be returned in the foreground process.
if (m_options.daemon && !s_daemonized) {
@ -36,10 +34,7 @@ application::run_result application::daemonize()
pid = fork();
if (pid < 0) {
// error
ret.success = false;
ret.errstr = "Could not fork.";
ret.proceed = false;
return ret;
return run_result::fatal("Could not fork.");
} else if (pid > 0) {
// parent. Write child pid to pidfile and exit
std::ofstream pidfile;
@ -59,10 +54,7 @@ application::run_result application::daemonize()
// Become own process group.
sid = setsid();
if (sid < 0) {
ret.success = false;
ret.errstr = string("Could not set session id.");
ret.proceed = false;
return ret;
return run_result::fatal("Could not set session id.");
}
// Set umask so no files are world anything or group writable.
@ -70,10 +62,7 @@ application::run_result application::daemonize()
// Change working directory to '/'
if ((chdir("/")) < 0) {
ret.success = false;
ret.errstr = string("Could not change working directory to '/'.");
ret.proceed = false;
return ret;
return run_result::fatal("Could not change working directory to '/'.");
}
// Close stdin, stdout, stderr and reopen to /dev/null
@ -87,5 +76,5 @@ application::run_result application::daemonize()
s_daemonized = true;
}
return ret;
return run_result::ok();
}

View File

@ -52,8 +52,6 @@ void application::configure_output_format()
application::run_result application::init_falco_engine()
{
run_result ret;
configure_output_format();
// Create "factories" that can create filters/formatters for syscalls
@ -75,7 +73,7 @@ application::run_result application::init_falco_engine()
{
if (m_state->enabled_sources.find(src) == m_state->enabled_sources.end())
{
throw std::invalid_argument("Attempted disabling unknown event source: " + src);
return run_result::fatal("Attempted disabling unknown event source: " + src);
}
m_state->enabled_sources.erase(src);
}
@ -83,10 +81,10 @@ application::run_result application::init_falco_engine()
// todo(jasondellaluce,leogr): change this once we attain multiple active source
if(m_state->enabled_sources.empty())
{
throw std::invalid_argument("At least one event source needs to be enabled");
return run_result::fatal("At least one event source needs to be enabled");
}
m_state->engine->set_min_priority(m_state->config->m_min_priority);
return ret;
return run_result::ok();
}

View File

@ -20,8 +20,6 @@ using namespace falco::app;
application::run_result application::init_inspector()
{
run_result ret;
m_state->inspector->set_buffer_format(m_options.event_buffer_format);
// If required, set the CRI paths
@ -108,5 +106,5 @@ application::run_result application::init_inspector()
}
#endif
return ret;
return run_result::ok();
}

View File

@ -23,8 +23,6 @@ using namespace falco::app;
application::run_result application::init_outputs()
{
run_result ret;
// read hostname
std::string hostname;
if(char* env_hostname = getenv("FALCO_GRPC_HOSTNAME"))
@ -37,9 +35,7 @@ application::run_result application::init_outputs()
int err = gethostname(c_hostname, 256);
if(err != 0)
{
ret.success = false;
ret.errstr = "Failed to get hostname";
ret.proceed = false;
return run_result::fatal("Failed to get hostname");
}
hostname = c_hostname;
}
@ -59,5 +55,5 @@ application::run_result application::init_outputs()
m_state->outputs->add_output(output);
}
return ret;
return run_result::ok();
}

View File

@ -22,29 +22,23 @@ using namespace falco::app;
application::run_result application::list_fields()
{
run_result ret;
if(m_options.list_fields)
{
if(m_options.list_source_fields != "" &&
!m_state->engine->is_source_valid(m_options.list_source_fields))
{
ret.success = false;
ret.errstr = "Value for --list must be a valid source type";
ret.proceed = false;
return ret;
return run_result::fatal("Value for --list must be a valid source type");
}
m_state->engine->list_fields(m_options.list_source_fields, m_options.verbose, m_options.names_only, m_options.markdown);
ret.proceed = false;
return run_result::exit();
}
if(m_options.list_syscall_events)
{
// We know this function doesn't hold into the raw pointer value
list_events(m_state->inspector.get(), m_options.markdown);
ret.proceed = false;
return run_result::exit();
}
return ret;
return run_result::ok();
}

View File

@ -21,8 +21,6 @@ using namespace falco::app;
application::run_result application::list_plugins()
{
run_result ret;
if(m_options.list_plugins)
{
std::ostringstream os;
@ -48,8 +46,8 @@ application::run_result application::list_plugins()
}
printf("%lu Plugins Loaded:\n\n%s\n", plugins.size(), os.str().c_str());
ret.proceed = false;
return run_result::exit();
}
return ret;
return run_result::ok();
}

View File

@ -20,8 +20,6 @@ using namespace falco::app;
application::run_result application::load_config()
{
run_result ret;
if (!m_options.conf_filename.empty())
{
m_state->config->init(m_options.conf_filename, m_options.cmdline_config_options);
@ -33,17 +31,14 @@ application::run_result application::load_config()
}
else
{
ret.success = false;
ret.proceed = false;
#ifndef BUILD_TYPE_RELEASE
ret.errstr = std::string("You must create a config file at ") + FALCO_SOURCE_CONF_FILE + ", " + FALCO_INSTALL_CONF_FILE + " or by passing -c";
return run_result::fatal(std::string("You must create a config file at ") + FALCO_SOURCE_CONF_FILE + ", " + FALCO_INSTALL_CONF_FILE + " or by passing -c");
#else
ret.errstr = std::string("You must create a config file at ") + FALCO_INSTALL_CONF_FILE + " or by passing -c";
return run_result::fatal(std::string("You must create a config file at ") + FALCO_INSTALL_CONF_FILE + " or by passing -c");
#endif
}
m_state->config->m_buffered_outputs = !m_options.unbuffered_outputs;
return ret;
return run_result::ok();
}

View File

@ -21,14 +21,10 @@ using namespace falco::app;
application::run_result application::load_plugins()
{
run_result ret;
#ifdef MUSL_OPTIMIZED
if (!m_state->config->m_plugins.empty())
{
ret.success = ret.proceed = false;
ret.errstr = "Can not load/use plugins with musl optimized build";
return ret;
return run_result::fatal("Can not load/use plugins with musl optimized build");
}
#endif
@ -48,12 +44,9 @@ application::run_result application::load_plugins()
// todo(jasondellaluce): change this once we support multiple enabled event sources
if(loaded_plugin)
{
ret.success = false;
ret.errstr = "Can not load multiple plugins with event sourcing capability: '"
return run_result::fatal("Can not load multiple plugins with event sourcing capability: '"
+ loaded_plugin->name()
+ "' already loaded";
ret.proceed = false;
return ret;
+ "' already loaded");
}
loaded_plugin = plugin;
m_state->enabled_sources = {plugin->event_source()};
@ -78,7 +71,7 @@ application::run_result application::load_plugins()
// stands because the plugin manager stores sources in a vector, and
// the syscall source is appended in the engine *after* the sources
// coming from plugins. Since this is an implementation-based
// assumption, we check this and throw an exception to spot
// assumption, we check this and return an error to spot
// regressions in the future. We keep it like this for to avoid the
// overhead of additional mappings at runtime, but we may consider
// mapping the two indexes under something like std::unordered_map in the future.
@ -87,9 +80,7 @@ application::run_result application::load_plugins()
auto source_idx_engine = m_state->engine->add_source(plugin->event_source(), filter_factory, formatter_factory);
if (!added || source_idx != source_idx_engine)
{
ret.success = ret.proceed = false;
ret.errstr = "Could not add event source in the engine: " + plugin->event_source();
return ret;
return run_result::fatal("Could not add event source in the engine: " + plugin->event_source());
}
}
}
@ -124,12 +115,10 @@ application::run_result application::load_plugins()
{
if (std::string(f.m_name) == fname)
{
ret.success = ret.proceed = false;
ret.errstr =
return run_result::fatal(
"Plugin '" + p->name()
+ "' supports extraction of field '" + fname
+ "' that is overlapping for source '" + it.first + "'";
return ret;
+ "' that is overlapping for source '" + it.first + "'");
}
}
}
@ -142,12 +131,10 @@ application::run_result application::load_plugins()
}
if (!used)
{
ret.success = ret.proceed = false;
ret.errstr = "Plugin '" + p->name()
+ "' has field extraction capability but is not compatible with any enabled event source";
return ret;
return run_result::fatal("Plugin '" + p->name()
+ "' has field extraction capability but is not compatible with any enabled event source");
}
}
return ret;
return run_result::ok();
}

View File

@ -70,8 +70,6 @@ void application::check_for_ignored_events()
application::run_result application::load_rules_files()
{
run_result ret;
string all_rules;
if (!m_options.rules_filenames.empty())
@ -81,10 +79,7 @@ application::run_result application::load_rules_files()
if(m_state->config->m_rules_filenames.empty())
{
ret.success = false;
ret.errstr = "You must specify at least one rules file/directory via -r or a rules_file entry in falco.yaml";
ret.proceed = false;
return ret;
return run_result::fatal("You must specify at least one rules file/directory via -r or a rules_file entry in falco.yaml");
}
falco_logger::log(LOG_DEBUG, "Configured rules filenames:\n");
@ -108,10 +103,7 @@ application::run_result application::load_rules_files()
}
catch(falco_exception &e)
{
ret.success = false;
ret.errstr = string("Could not load rules file ") + filename + ": " + e.what();
ret.proceed = false;
return ret;
return run_result::fatal(string("Could not load rules file ") + filename + ": " + e.what());
}
m_state->required_engine_versions[filename] = required_engine_version;
}
@ -128,10 +120,7 @@ application::run_result application::load_rules_files()
}
if (!m_state->engine->check_plugin_requirements(plugin_reqs, plugin_vers_err))
{
ret.success = false;
ret.errstr = plugin_vers_err;
ret.proceed = false;
return ret;
return run_result::fatal(plugin_vers_err);
}
// Free-up memory for the rule loader, which is not used from now on
@ -175,16 +164,14 @@ application::run_result application::load_rules_files()
if (m_options.describe_all_rules)
{
m_state->engine->describe_rule(NULL);
ret.proceed = false;
return ret;
return run_result::exit();
}
if (!m_options.describe_rule.empty())
{
m_state->engine->describe_rule(&(m_options.describe_rule));
ret.proceed = false;
return ret;
return run_result::exit();
}
return ret;
return run_result::ok();
}

View File

@ -26,8 +26,6 @@ typedef std::function<void(std::shared_ptr<sinsp> inspector)> open_t;
application::run_result application::open_inspector()
{
run_result ret;
if(is_capture_mode())
{
// Try to open the trace file as a
@ -38,10 +36,7 @@ application::run_result application::open_inspector()
}
catch(sinsp_exception &e)
{
ret.success = false;
ret.errstr = std::string("Could not open trace filename ") + m_options.trace_filename + " for reading: " + e.what();
ret.proceed = false;
return ret;
return run_result::fatal("Could not open trace filename " + m_options.trace_filename + " for reading: " + e.what());
}
}
else
@ -75,10 +70,7 @@ application::run_result application::open_inspector()
}
else
{
ret.success = false;
ret.errstr = e.what();
ret.proceed = false;
return ret;
return run_result::fatal(e.what());
}
}
}
@ -89,7 +81,7 @@ application::run_result application::open_inspector()
m_state->inspector->start_dropping_mode(1);
}
return ret;
return run_result::ok();
}
bool application::close_inspector(std::string &errstr)

View File

@ -20,13 +20,10 @@ using namespace falco::app;
application::run_result application::print_help()
{
run_result ret;
if(m_options.help)
{
printf("%s", m_options.usage().c_str());
ret.proceed = false;
return run_result::exit();
}
return ret;
return run_result::ok();
}

View File

@ -61,13 +61,10 @@ void application::print_all_ignored_events()
application::run_result application::print_ignored_events()
{
run_result ret;
if(m_options.print_ignored_events)
{
print_all_ignored_events();
ret.proceed = false;
return run_result::exit();
}
return ret;
return run_result::ok();
}

View File

@ -32,8 +32,6 @@ static std::string read_file(std::string &filename)
application::run_result application::print_support()
{
run_result ret;
if(m_options.print_support)
{
nlohmann::json support;
@ -42,10 +40,7 @@ application::run_result application::print_support()
if(uname(&sysinfo) != 0)
{
ret.success = false;
ret.errstr = string("Could not uname() to find system info: ") + strerror(errno);
ret.proceed = false;
return ret;
return run_result::fatal(string("Could not uname() to find system info: ") + strerror(errno));
}
support["version"] = FALCO_VERSION;
@ -70,8 +65,8 @@ application::run_result application::print_support()
}
printf("%s\n", support.dump().c_str());
ret.proceed = false;
return run_result::exit();
}
return ret;
return run_result::ok();
}

View File

@ -21,14 +21,11 @@ using namespace falco::app;
application::run_result application::print_version()
{
run_result ret;
if(m_options.print_version_info)
{
printf("Falco version: %s\n", FALCO_VERSION);
printf("Driver version: %s\n", DRIVER_VERSION);
ret.proceed = false;
return run_result::exit();
}
return ret;
return run_result::ok();
}

View File

@ -36,11 +36,10 @@ using namespace falco::app;
//
// Event processing loop
//
uint64_t application::do_inspect(syscall_evt_drop_mgr &sdropmgr,
application::run_result application::do_inspect(syscall_evt_drop_mgr &sdropmgr,
uint64_t duration_to_tot_ns,
application::run_result &result)
uint64_t &num_evts)
{
uint64_t num_evts = 0;
int32_t rc;
sinsp_evt* ev;
StatsFileWriter writer;
@ -49,6 +48,8 @@ uint64_t application::do_inspect(syscall_evt_drop_mgr &sdropmgr,
std::size_t source_idx;
bool source_idx_found = false;
num_evts = 0;
sdropmgr.init(m_state->inspector,
m_state->outputs,
m_state->config->m_syscall_evt_drop_actions,
@ -63,7 +64,7 @@ uint64_t application::do_inspect(syscall_evt_drop_mgr &sdropmgr,
if (!writer.init(m_state->inspector, m_options.stats_filename, m_options.stats_interval, errstr))
{
throw falco_exception(errstr);
return run_result::fatal(errstr);
}
}
@ -131,7 +132,7 @@ uint64_t application::do_inspect(syscall_evt_drop_mgr &sdropmgr,
// Event read error.
//
cerr << "rc = " << rc << endl;
throw sinsp_exception(m_state->inspector->getlasterr().c_str());
return run_result::fatal(m_state->inspector->getlasterr());
}
// Reset the timeouts counter, Falco successfully got an event to process
@ -150,10 +151,7 @@ uint64_t application::do_inspect(syscall_evt_drop_mgr &sdropmgr,
if(!sdropmgr.process_event(m_state->inspector, ev))
{
result.success = false;
result.errstr = "";
result.proceed = false;
break;
return run_result::fatal("Drop manager internal error");
}
if(!ev->simple_consumer_consider() && !m_options.all_events)
@ -170,10 +168,7 @@ uint64_t application::do_inspect(syscall_evt_drop_mgr &sdropmgr,
source_idx = m_state->inspector->get_plugin_manager()->source_idx_by_plugin_id(*(int32_t *)ev->get_param(0)->m_val, source_idx_found);
if (!source_idx_found)
{
result.success = false;
result.errstr = "Unknown plugin ID in inspector: " + std::to_string(*(int32_t *)ev->get_param(0)->m_val);
result.proceed = false;
break;
return run_result::fatal("Unknown plugin ID in inspector: " + std::to_string(*(int32_t *)ev->get_param(0)->m_val));
}
}
@ -191,7 +186,7 @@ uint64_t application::do_inspect(syscall_evt_drop_mgr &sdropmgr,
num_evts++;
}
return num_evts;
return run_result::ok();
}
application::run_result application::process_events()
@ -200,14 +195,14 @@ application::run_result application::process_events()
// Used for stats
double duration;
scap_stats cstats;
uint64_t num_evts = 0;
run_result ret;
duration = ((double)clock()) / CLOCKS_PER_SEC;
uint64_t num_evts = do_inspect(sdropmgr,
ret = do_inspect(sdropmgr,
uint64_t(m_options.duration_to_tot*ONE_SECOND_IN_NS),
ret);
num_evts);
duration = ((double)clock()) / CLOCKS_PER_SEC - duration;

View File

@ -24,8 +24,6 @@ using namespace falco::app;
application::run_result application::start_grpc_server()
{
run_result ret;
// gRPC server
if(m_state->config->m_grpc_enabled)
{
@ -44,7 +42,7 @@ application::run_result application::start_grpc_server()
m_state->grpc_server.run();
});
}
return ret;
return run_result::ok();
}
bool application::stop_grpc_server(std::string &errstr)

View File

@ -24,7 +24,6 @@ using namespace falco::app;
application::run_result application::start_webserver()
{
run_result ret;
if(!is_capture_mode() && m_state->config->m_webserver_enabled)
{
std::string ssl_option = (m_state->config->m_webserver_ssl_enabled ? " (SSL)" : "");
@ -35,7 +34,7 @@ application::run_result application::start_webserver()
m_state->config->m_webserver_ssl_certificate,
m_state->config->m_webserver_ssl_enabled);
}
return ret;
return run_result::ok();
}
bool application::stop_webserver(std::string &errstr)

View File

@ -20,8 +20,6 @@ using namespace falco::app;
application::run_result application::validate_rules_files()
{
run_result ret;
if(m_options.validate_rules_filenames.size() > 0)
{
falco_logger::log(LOG_INFO, "Validating rules file(s):\n");
@ -39,15 +37,13 @@ application::run_result application::validate_rules_files()
catch(falco_exception &e)
{
printf("%s%s", prefix.c_str(), e.what());
ret.success = false;
ret.errstr = prefix + e.what();
ret.proceed = false;
return ret;
return run_result::fatal(prefix + e.what());
}
printf("%sOk\n", prefix.c_str());
}
falco_logger::log(LOG_INFO, "Ok\n");
return run_result::exit();
}
return ret;
return run_result::ok();
}

View File

@ -139,11 +139,11 @@ bool application::run(std::string &errstr, bool &restart)
std::bind(&application::attach_inotify_signals, this),
std::bind(&application::daemonize, this),
std::bind(&application::init_outputs, this),
std::bind(&application::open_inspector, this),
#ifndef MINIMAL_BUILD
std::bind(&application::start_grpc_server, this),
std::bind(&application::start_webserver, this),
#endif
std::bind(&application::open_inspector, this),
std::bind(&application::process_events, this)
};

View File

@ -95,16 +95,41 @@ private:
// Used in the below methods to indicate how to proceed.
struct run_result {
// Successful result
inline static run_result ok()
{
run_result r;
r.success = true;
r.errstr = "";
r.proceed = true;
return r;
}
// Successful result that causes the program to stop
inline static run_result exit()
{
run_result r = ok();
r.proceed = false;
return r;
}
// Failure result that causes the program to stop with an error
inline static run_result fatal(std::string err)
{
run_result r;
r.success = false;
r.errstr = err;
r.proceed = false;
return r;
}
run_result();
virtual ~run_result();
// If true, the method completed successfully.
bool success;
// If success==false, details on the error.
std::string errstr;
// If true, subsequent methods should be performed. If
// false, subsequent methods should *not* be performed
// and falco should tear down/exit/restart.
@ -150,9 +175,9 @@ private:
void configure_output_format();
void check_for_ignored_events();
void print_all_ignored_events();
uint64_t do_inspect(syscall_evt_drop_mgr &sdropmgr,
run_result do_inspect(syscall_evt_drop_mgr &sdropmgr,
uint64_t duration_to_tot_ns,
run_result &result);
uint64_t &num_events);
inline bool is_syscall_source_enabled() const
{

View File

@ -43,7 +43,6 @@ static void display_fatal_err(const string &msg)
int falco_init(int argc, char **argv, bool &restart)
{
falco::app::application app;
int result = EXIT_SUCCESS;
restart = false;
std::string errstr;
@ -64,18 +63,17 @@ int falco_init(int argc, char **argv, bool &restart)
if(!success)
{
result = EXIT_FAILURE;
fprintf(stderr, "%s\n", errstr.c_str());
fprintf(stderr, "Error: %s\n", errstr.c_str());
return EXIT_FAILURE;
}
}
catch(exception &e)
{
display_fatal_err("Runtime error: " + string(e.what()) + ". Exiting.\n");
result = EXIT_FAILURE;
return EXIT_FAILURE;
}
return result;
return EXIT_SUCCESS;
}
//