Fawkes API Fawkes Development Version
run.cpp
1
2/***************************************************************************
3 * run.cpp - Fawkes run functions
4 *
5 * Created: Wed May 04 23:23:23 2011
6 * Copyright 2006-2011 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. A runtime exception applies to
14 * this software (see LICENSE.GPL_WRE file mentioned below for details).
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22 */
23
24#include <baseapp/daemonize.h>
25#include <baseapp/main_thread.h>
26#include <baseapp/run.h>
27#include <baseapp/thread_manager.h>
28#include <core/threading/thread.h>
29
30#ifdef HAVE_BLACKBOARD
31# include <blackboard/local.h>
32#endif
33#include <config/sqlite.h>
34#include <config/yaml.h>
35#ifdef HAVE_CONFIG_NETWORK_HANDLER
36# include <config/net_handler.h>
37#endif
38#include <logging/console.h>
39#include <logging/factory.h>
40#include <logging/liblogger.h>
41#include <logging/multi.h>
42#include <utils/ipc/shm.h>
43#include <utils/system/argparser.h>
44#ifdef HAVE_NETWORK_LOGGER
45# include <network_logger/network_logger.h>
46#endif
47#ifdef HAVE_LOGGING_FD_REDIRECT
48# include <logging/fd_redirect.h>
49#endif
50#include <utils/time/clock.h>
51#include <utils/time/time.h>
52#ifdef HAVE_NETWORK_MANAGER
53# include <netcomm/fawkes/network_manager.h>
54#endif
55#include <plugin/manager.h>
56#ifdef HAVE_PLUGIN_NETWORK_HANDLER
57# include <plugin/net/handler.h>
58#endif
59#include <aspect/manager.h>
60#include <syncpoint/syncpoint_manager.h>
61#ifdef HAVE_TF
62# include <tf/transform_listener.h>
63# include <tf/transformer.h>
64#endif
65
66#include <sys/stat.h>
67#include <sys/types.h>
68
69#include <cstdio>
70#include <cstdlib>
71#include <cstring>
72#include <fnmatch.h>
73#include <grp.h>
74#include <pwd.h>
75#include <signal.h>
76#include <unistd.h>
77
78namespace fawkes {
79
80class BlackBoard;
81class FawkesNetworkManager;
82
83namespace runtime {
84
85ArgumentParser * argument_parser = NULL;
86FawkesMainThread * main_thread = NULL;
87MultiLogger * logger = NULL;
88NetworkLogger * network_logger = NULL;
89BlackBoard * blackboard = NULL;
90Configuration * config = NULL;
91PluginManager * plugin_manager = NULL;
92AspectManager * aspect_manager = NULL;
93ThreadManager * thread_manager = NULL;
94FawkesNetworkManager * network_manager = NULL;
95ConfigNetworkHandler * nethandler_config = NULL;
96PluginNetworkHandler * nethandler_plugin = NULL;
97Clock * clock = NULL;
98SharedMemoryRegistry * shm_registry;
99InitOptions * init_options = NULL;
100tf::Transformer * tf_transformer = NULL;
101tf::TransformListener *tf_listener = NULL;
102Time * start_time = NULL;
103SyncPointManager * syncpoint_manager = NULL;
104#ifdef HAVE_LOGGING_FD_REDIRECT
105LogFileDescriptorToLog *log_fd_redirect_stderr_ = NULL;
106LogFileDescriptorToLog *log_fd_redirect_stdout_ = NULL;
107#endif
108
109// this is NOT shared to the outside
110FawkesMainThread::Runner *runner = NULL;
111
112bool
113init(int argc, char **argv, int &retval)
114{
115 return init(InitOptions(argc, argv), retval);
116}
117
118bool
119init(const InitOptions &options, int &retval)
120{
121 init_options = new InitOptions(options);
122
123 if (init_options->show_help())
124 return true;
125
126 if (options.daemonize()) {
127 fawkes::daemon::init(options.daemon_pid_file(), options.basename());
128 if (options.daemonize_kill()) {
129 fawkes::daemon::kill();
130 retval = 0;
131 return false;
132 } else if (options.daemonize_status()) {
133 retval = fawkes::daemon::running() ? 0 : 1;
134 return false;
135 } else {
136 if (fawkes::daemon::start()) {
137 retval = 0;
138 return false;
139 }
140 }
141 }
142
143 // *** set user group if requested
144 const char *user = NULL;
145 const char *group = NULL;
146 if (options.has_username()) {
147 user = options.username();
148 }
149 if (options.has_groupname()) {
150 group = options.groupname();
151 }
152
153 if (user != NULL) {
154 struct passwd *pw;
155 if (!(pw = getpwnam(user))) {
156 printf("Failed to find user %s, check -u argument.\n", user);
157 retval = 203;
158 return false;
159 }
160 int r = 0;
161 r = setreuid(pw->pw_uid, pw->pw_uid);
162 if (r < 0) {
163 perror("Failed to drop privileges (user)");
164 }
165 }
166
167 if (group != NULL) {
168 struct group *gr;
169 if (!(gr = getgrnam(group))) {
170 printf("Failed to find group %s, check -g argument.\n", user);
171 retval = 204;
172 return false;
173 }
174 int r = 0;
175 r = setregid(gr->gr_gid, gr->gr_gid);
176 if (r < 0) {
177 perror("Failed to drop privileges (group)");
178 }
179 }
180
181 // *** setup base thread and shm registry
183
184 shm_registry = NULL;
185 struct passwd *uid_pw = getpwuid(getuid());
186 if (uid_pw == NULL) {
187 shm_registry = new SharedMemoryRegistry();
188 } else {
189 char *registry_name;
190 if (asprintf(&registry_name, USER_SHM_NAME, uid_pw->pw_name) == -1) {
191 shm_registry = new SharedMemoryRegistry();
192 } else {
193 shm_registry = new SharedMemoryRegistry(registry_name);
194 free(registry_name);
195 }
196 }
197
198 if (!shm_registry) {
199 throw Exception("Failed to create shared memory registry");
200 }
201
202 // *** setup logging
203 if (options.has_loggers()) {
204 try {
205 logger = LoggerFactory::multilogger_instance(options.loggers());
206 } catch (Exception &e) {
207 e.append("Initializing multi logger failed");
208 throw;
209 }
210 } else {
211 logger = new MultiLogger(new ConsoleLogger());
212 }
213
214 logger->set_loglevel(options.log_level());
215 LibLogger::init(logger);
216
217 // *** Prepare home dir directory, just in case
218 const char *homedir = getenv("HOME");
219 if (homedir) {
220 char *userdir;
221 if (asprintf(&userdir, "%s/%s", homedir, USERDIR) != -1) {
222 if (access(userdir, W_OK) != 0) {
223 if (mkdir(userdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) {
224 logger->log_warn("FawkesMainThread",
225 "Failed to create .fawkes "
226 "directory %s, trying without",
227 userdir);
228 }
229 }
230 free(userdir);
231 }
232 }
233
234 // *** setup config
235
236 SQLiteConfiguration *sqconfig = NULL;
237
238 if (options.config_file() && fnmatch("*.sql", options.config_file(), FNM_PATHNAME) == 0) {
239 sqconfig = new SQLiteConfiguration(CONFDIR);
240 config = sqconfig;
241 } else {
242 config = new YamlConfiguration(CONFDIR);
243 }
244
245 config->load(options.config_file());
246
247 if (sqconfig) {
248 try {
249 SQLiteConfiguration::SQLiteValueIterator *i = sqconfig->modified_iterator();
250 while (i->next()) {
251 std::string modtype = i->get_modtype();
252 if (modtype == "changed") {
253 logger->log_warn("FawkesMainThread",
254 "Default config value CHANGED: %s"
255 "(was: %s now: %s)",
256 i->path(),
257 i->get_oldvalue().c_str(),
258 i->get_as_string().c_str());
259 } else if (modtype == "erased") {
260 logger->log_warn("FawkesMainThread", "Default config value ERASED: %s", i->path());
261 } else {
262 logger->log_debug("FawkesMainThread",
263 "Default config value ADDED: %s "
264 "(value: %s)",
265 i->path(),
266 i->get_as_string().c_str());
267 }
268 }
269 delete i;
270 } catch (Exception &e) {
271 logger->log_warn("FawkesMainThread",
272 "Failed to read modified default "
273 "config values, no dump?");
274 }
275 }
276
277 if (!options.has_loggers()) {
278 // Allow configuration override from config
279 if (config->exists("/fawkes/mainapp/loggers")) {
280 try {
281 std::string loggers = config->get_string("/fawkes/mainapp/loggers");
282 MultiLogger *new_logger =
283 LoggerFactory::multilogger_instance(loggers.c_str(), options.log_level());
284 logger = new_logger;
286 LibLogger::init(new_logger);
287 } catch (Exception &e) {
288 logger->log_warn("FawkesMainThread",
289 "Loggers set in config file, "
290 "but failed to read, exception follows.");
291 logger->log_warn("FawkesMainThread", e);
292 }
293 }
294 }
295
296 if (config->exists("/fawkes/mainapp/log_stderr_as_warn")) {
297 try {
298 bool log_stderr_as_warn = config->get_bool("/fawkes/mainapp/log_stderr_as_warn");
299 if (log_stderr_as_warn) {
300#ifdef HAVE_LOGGING_FD_REDIRECT
301 log_fd_redirect_stderr_ =
302 new LogFileDescriptorToLog(STDERR_FILENO, logger, "stderr", Logger::LL_WARN);
303#else
304 logger->log_warn("FawkesMainThread",
305 "stderr log redirection enabled but not available at compile time");
306#endif
307 }
308 } catch (Exception &e) {
309 } // ignored
310 }
311
312 // *** Determine network parameters
313 bool enable_ipv4 = true;
314 bool enable_ipv6 = true;
315 std::string listen_ipv4;
316 std::string listen_ipv6;
317 unsigned int net_tcp_port = 1910;
318 std::string net_service_name = "Fawkes on %h";
319 if (options.has_net_tcp_port()) {
320 net_tcp_port = options.net_tcp_port();
321 } else {
322 try {
323 net_tcp_port = config->get_uint("/network/fawkes/tcp_port");
324 } catch (Exception &e) {
325 } // ignore, we stick with the default
326 }
327
328 if (options.has_net_service_name()) {
329 net_service_name = options.net_service_name();
330 } else {
331 try {
332 net_service_name = config->get_string("/network/fawkes/service_name");
333 } catch (Exception &e) {
334 } // ignore, we stick with the default
335 }
336
337 if (net_tcp_port > 65535) {
338 logger->log_warn("FawkesMainThread", "Invalid port '%u', using 1910", net_tcp_port);
339 net_tcp_port = 1910;
340 }
341
342 try {
343 enable_ipv4 = config->get_bool("/network/ipv4/enable");
344 } catch (Exception &e) {
345 } // ignore, we stick with the default
346 try {
347 enable_ipv6 = config->get_bool("/network/ipv6/enable");
348 } catch (Exception &e) {
349 } // ignore, we stick with the default
350
351 try {
352 listen_ipv4 = config->get_string("/network/ipv4/listen");
353 } catch (Exception &e) {
354 } // ignore, we stick with the default
355 try {
356 listen_ipv6 = config->get_string("/network/ipv6/listen");
357 } catch (Exception &e) {
358 } // ignore, we stick with the default
359
360 if (!enable_ipv4) {
361 logger->log_warn("FawkesMainThread", "Disabling IPv4 support");
362 }
363 if (!enable_ipv6) {
364 logger->log_warn("FawkesMainThread", "Disabling IPv6 support");
365 }
366 if (!listen_ipv4.empty()) {
367 logger->log_info("FawkesMainThread", "Listening on IPv4 address %s", listen_ipv4.c_str());
368 }
369 if (!listen_ipv6.empty()) {
370 logger->log_info("FawkesMainThread", "Listening on IPv6 address %s", listen_ipv4.c_str());
371 }
372
373#ifdef HAVE_BLACKBOARD
374 // *** Setup blackboard
375 std::string bb_magic_token = "";
376 unsigned int bb_size = 2097152;
377 try {
378 bb_magic_token = config->get_string("/fawkes/mainapp/blackboard_magic_token");
379 logger->log_info("FawkesMainApp",
380 "BlackBoard magic token defined. "
381 "Using shared memory BlackBoard.");
382 } catch (Exception &e) {
383 // ignore
384 }
385 try {
386 bb_size = config->get_uint("/fawkes/mainapp/blackboard_size");
387 } catch (Exception &e) {
388 logger->log_warn("FawkesMainApp",
389 "BlackBoard size not defined. "
390 "Will use %u, saving to default DB",
391 bb_size);
392 config->set_default_uint("/fawkes/mainapp/blackboard_size", bb_size);
393 }
394
395 // Cleanup stale BlackBoard shared memory segments if requested
396 if (options.bb_cleanup()) {
397 LocalBlackBoard::cleanup(bb_magic_token.c_str(),
398 /* output with lister? */ true);
400 }
401
402 LocalBlackBoard *lbb = NULL;
403 if (bb_magic_token == "") {
404 lbb = new LocalBlackBoard(bb_size);
405 } else {
406 lbb = new LocalBlackBoard(bb_size, bb_magic_token.c_str());
407 }
408 blackboard = lbb;
409#endif
410
411#ifdef HAVE_TF
412 tf_transformer = new tf::Transformer();
413 tf_listener = new tf::TransformListener(blackboard, tf_transformer);
414#endif
415
416 aspect_manager = new AspectManager();
417 thread_manager = new ThreadManager(aspect_manager, aspect_manager);
418
419 syncpoint_manager = new SyncPointManager(logger);
420
421 plugin_manager = new PluginManager(thread_manager,
422 config,
423 "/fawkes/meta_plugins/",
424 options.plugin_module_flags(),
425 options.init_plugin_cache());
426#ifdef HAVE_NETWORK_MANAGER
427 network_manager = new FawkesNetworkManager(thread_manager,
428 enable_ipv4,
429 enable_ipv6,
430 listen_ipv4,
431 listen_ipv6,
432 net_tcp_port,
433 net_service_name.c_str());
434# ifdef HAVE_CONFIG_NETWORK_HANDLER
435 nethandler_config = new ConfigNetworkHandler(config, network_manager->hub());
436# endif
437# ifdef HAVE_PLUGIN_NETWORK_HANDLER
438 nethandler_plugin = new PluginNetworkHandler(plugin_manager, network_manager->hub());
439 nethandler_plugin->start();
440# endif
441# ifdef HAVE_NETWORK_LOGGER
442 network_logger = new NetworkLogger(network_manager->hub(), logger->loglevel());
443 logger->add_logger(network_logger);
444# endif
445#endif
446
447 clock = Clock::instance();
448 start_time = new Time(clock);
449
450#if defined(HAVE_NETWORK_MANAGER) && defined(HAVE_BLACKBOARD)
451 lbb->start_nethandler(network_manager->hub());
452#endif
453
454 // *** Create main thread, but do not start, yet
455 main_thread = new fawkes::FawkesMainThread(config,
456 logger,
457 thread_manager,
458 syncpoint_manager,
459 plugin_manager,
460 options.load_plugin_list(),
461 options.default_plugin());
462
463 aspect_manager->register_default_inifins(blackboard,
464 thread_manager->aspect_collector(),
465 config,
466 logger,
467 clock,
468#ifdef HAVE_NETWORK_MANAGER
469 network_manager->hub(),
470#else
471 NULL,
472#endif
473 main_thread,
474 logger,
475 thread_manager,
476#ifdef HAVE_NETWORK_MANAGER
477 network_manager->nnresolver(),
478 network_manager->service_publisher(),
479 network_manager->service_browser(),
480#else
481 NULL,
482 NULL,
483 NULL,
484#endif
485 plugin_manager,
486 tf_transformer,
487 syncpoint_manager);
488
489 retval = 0;
490 return true;
491}
492
493void
494cleanup()
495{
496 if (init_options->daemonize()) {
497 fawkes::daemon::cleanup();
498 }
499
500#ifdef HAVE_PLUGIN_NETWORK_HANDLER
501 if (nethandler_plugin) {
502 nethandler_plugin->cancel();
503 nethandler_plugin->join();
504 }
505#endif
506
507#ifdef HAVE_NETWORK_LOGGER
508 if (logger) {
509 // Must delete network logger first since network manager
510 // has to die before the LibLogger is finalized.
511 logger->remove_logger(network_logger);
512 delete network_logger;
513 }
514#endif
515
516#ifdef HAVE_CONFIG_NETWORK_HANDLER
517 delete nethandler_config;
518#endif
519#ifdef HAVE_PLUGIN_NETWORK_HANDLER
520 delete nethandler_plugin;
521#endif
522 delete plugin_manager;
523 delete main_thread;
524#ifdef HAVE_TF
525 delete tf_listener;
526 delete tf_transformer;
527#endif
528#ifdef HAVE_BLACKBOARD
529 delete blackboard;
530#endif
531 delete config;
532 delete argument_parser;
533 delete init_options;
534#ifdef HAVE_NETWORK_MANAGER
535 delete network_manager;
536#endif
537 delete thread_manager;
538 delete aspect_manager;
539 delete shm_registry;
540#ifdef HAVE_LOGGING_FD_REDIRECT
541 delete log_fd_redirect_stderr_;
542 delete log_fd_redirect_stdout_;
543#endif
544
545 main_thread = NULL;
546 argument_parser = NULL;
547 init_options = NULL;
548 nethandler_config = NULL;
549 nethandler_plugin = NULL;
550 plugin_manager = NULL;
551 network_manager = NULL;
552 config = NULL;
553 thread_manager = NULL;
554 aspect_manager = NULL;
555 shm_registry = NULL;
556 blackboard = NULL;
557#ifdef HAVE_LOGGING_FD_REDIRECT
558 log_fd_redirect_stderr_ = NULL;
559 log_fd_redirect_stdout_ = NULL;
560#endif
561
562 // implicitly frees multi_logger and all sub-loggers
564 logger = NULL;
565
566 delete start_time;
567 start_time = NULL;
569 clock = NULL;
570
571 try {
573 } catch (Exception &e) {
574 } // ignored, can fire on show_help
575
576 // should be last, because of not disabled this hosts the
577 // default signal handlers
578 delete runner;
579 runner = 0;
580}
581
582void
583run()
584{
585 if (init_options->show_help()) {
586 print_usage(init_options->basename());
587 return;
588 }
589
590 bool defsigs = init_options->default_signal_handlers();
591 runner = new FawkesMainThread::Runner(main_thread, defsigs);
592
593 try {
594 runner->run();
595 } catch (Exception &e) {
596 printf("Running Fawkes failed\n");
597 e.print_trace();
598 }
599}
600
601/** Quit Fawkes.
602 * You can call this from within Fawkes to quit Fawkes. Use with extreme care an
603 * only rarely.
604 * This sends SIGINT to the local process. This triggers the quit routine but also
605 * takes a currently running init into account. This is prone to the same potential
606 * problems as a SIGINT received otherwise, e.g. a never-ending thread blocking
607 * the main thread from cancelling.
608 */
609void
610quit()
611{
612 kill(getpid(), SIGINT);
613}
614
615void
616print_usage(const char *progname)
617{
618 printf("Fawkes Main Application - Usage Instructions\n"
619 "================================================"
620 "===============================\n"
621 "Usage: %s [options] [plugins]\n"
622 "where\n"
623 " [plugins] is a space-separated list of plugins to load on startup in given order\n"
624 " [options] is one or more of:\n"
625 " -h These help instructions\n"
626 " -C Cleanup old BB and shared memory segments\n"
627 " -c config file Configuration file to load.\n"
628 " Examples: default.sql or config.yaml\n"
629 " -d Enable debug output\n"
630 " -q[qqq] Quiet mode, -q omits debug, -qq debug and"
631 "info,\n "
632 "-qqq omit debug, info and warn, -qqqq no output\n"
633 " -l level Set log level directly mutually exclusive"
634 "with -q,\n "
635 "level is one of debug, info, warn, error, or none\n"
636 " -L loggers Define loggers. By default this setting is"
637 "read from\n "
638 "config (console logger if unset). Format is:\n"
639 " logger:args[;logger2:args2[!...]]\n"
640 " Currently supported:\n"
641 " console, file:file.log, network logger always added\n"
642 " -p plugins List of plugins to load on startup in given order\n"
643 " -P port TCP port to listen on for Fawkes network connections.\n"
644 " --net-service-name=name mDNS service name to use.\n"
645 " -u user Drop privileges and run as given user.\n"
646 " -g group Drop privileges and run as given group.\n"
647#ifdef HAVE_LIBDAEMON
648 " -D[pid file] Run daemonized in the background, pid file "
649 "is optional,\n "
650 "default is /var/run/fawkes.pid, must be absolute path.\n"
651 " -D[pid file] -k Kill a daemonized Fawkes running in the"
652 "background\n"
653 " -D[pid file] -s Check status of daemon.\n"
654#endif
655 "\n",
656 progname);
657}
658
659/** Get Fawkes uptime.
660 * Returns the time in seconds since Fawkes was started.
661 * This creates a new time for the system clock and subtracts the start time.
662 * @return time in seconds since Fawkes was started
663 */
664float
665uptime()
666{
667 if (start_time) {
668 fawkes::Time now(clock);
669 return now - start_time;
670 } else {
671 return 0.0;
672 }
673}
674
675} // end namespace runtime
676} // end namespace fawkes
void register_default_inifins(BlackBoard *blackboard, ThreadCollector *collector, Configuration *config, Logger *logger, Clock *clock, FawkesNetworkHub *fnethub, MainLoopEmployer *mloop_employer, LoggerEmployer *logger_employer, BlockedTimingExecutor *btexec, NetworkNameResolver *nnresolver, ServicePublisher *service_publisher, ServiceBrowser *service_browser, PluginManager *pmanager, tf::Transformer *tf_listener, SyncPointManager *syncpoint_manager)
Register default aspect initializer/finalizer.
Definition: manager.cpp:227
static void finalize()
Finalize.
Definition: clock.cpp:74
static Clock * instance()
Clock initializer.
Definition: clock.cpp:63
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
virtual void load(const char *file_path)=0
Load configuration.
virtual bool exists(const char *path)=0
Check if a given value exists.
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
virtual void set_default_uint(const char *path, unsigned int uint)=0
Set new default value in configuration of type unsigned int.
void run()
Run main thread.
Fawkes default main thread.
Definition: main_thread.h:59
FawkesNetworkHub * hub()
Get Fawkes network hub.
NetworkNameResolver * nnresolver()
Get network name resolver.
ServiceBrowser * service_browser()
Get service browser.
ServicePublisher * service_publisher()
Get service publisher.
static void init(MultiLogger *multi_logger=NULL)
Initialize logger.
Definition: liblogger.cpp:60
static void finalize()
Delete internal logger.
Definition: liblogger.cpp:78
static void cleanup(const char *magic_token, bool use_lister=false)
Cleanup orphaned BlackBoard segments.
Definition: local.cpp:164
static MultiLogger * multilogger_instance(const char *as, Logger::LogLevel default_ll=Logger::LL_DEBUG)
Create MultiLogger instance.
Definition: factory.cpp:142
virtual LogLevel loglevel()
Get log level.
Definition: logger.cpp:267
@ LL_WARN
warning, should be investigated but software still functions, an example is that something was reques...
Definition: logger.h:54
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: multi.cpp:195
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: multi.cpp:139
void add_logger(Logger *logger)
Add a logger.
Definition: multi.cpp:110
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: multi.cpp:216
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: multi.cpp:174
void remove_logger(Logger *logger)
Remove logger.
Definition: multi.cpp:128
static void cleanup(const char *name=0)
Cleanup existing shared memory segments.
ThreadCollector * aspect_collector() const
Get a thread collector to be used for an aspect initializer.
static void destroy_main()
Destroy main thread wrapper instance.
Definition: thread.cpp:1289
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:499
static void init_main()
Initialize Thread wrapper instance for main thread.
Definition: thread.cpp:1276
void join()
Join the thread.
Definition: thread.cpp:597
void cancel()
Cancel a thread.
Definition: thread.cpp:646
A class for handling time.
Definition: time.h:93
InitOptions & show_help(bool show_help)
Set to show help.
InitOptions & default_signal_handlers(bool enable)
Set default signal handlers.
InitOptions & daemonize(bool daemonize, bool kill=false, bool status=false, const char *pid_file=0)
Set daemonization options.
const char * basename() const
Get program basename.
Fawkes library namespace.