24 #include <baseapp/main_thread.h>
26 #include <core/threading/interruptible_barrier.h>
27 #include <core/threading/mutex_locker.h>
28 #include <core/exceptions/system.h>
29 #include <core/version.h>
30 #include <config/sqlite.h>
31 #include <utils/time/clock.h>
32 #include <utils/time/wait.h>
33 #include <netcomm/fawkes/network_manager.h>
34 #include <blackboard/local.h>
36 #include <aspect/manager.h>
37 #include <plugin/manager.h>
38 #include <plugin/loader.h>
39 #include <plugin/net/handler.h>
47 #include <core/macros.h>
77 const char *load_plugins,
78 const char *default_plugin)
79 :
Thread(
"FawkesMainThread")
81 __plugin_manager = plugin_manager;
82 __thread_manager = thread_manager;
83 __multi_logger = multi_logger;
84 __sqlite_conf = config;
87 __mainloop_thread = NULL;
88 __mainloop_mutex =
new Mutex();
91 __load_plugins = NULL;
93 __load_plugins = strdup(load_plugins);
96 __default_plugin = NULL;
98 __default_plugin = strdup(default_plugin);
104 __loop_start =
new Time(__clock);
105 __loop_end =
new Time(__clock);
107 __max_thread_time_usec = __config->
get_uint(
"/fawkes/mainapp/max_thread_time");
109 __max_thread_time_usec = 30000;
110 __multi_logger->
log_info(
"FawkesMainApp",
111 "Maximum thread time not set, assuming 30ms.");
113 __max_thread_time_nanosec = __max_thread_time_usec * 1000;
117 __desired_loop_time_usec =
118 __config->
get_uint(
"/fawkes/mainapp/desired_loop_time");
119 if ( __desired_loop_time_usec > 0 ) {
120 __time_wait =
new TimeWait(__clock, __desired_loop_time_usec);
123 __desired_loop_time_usec = 0;
124 __multi_logger->
log_info(
"FawkesMainApp",
125 "Desired loop time not set, assuming 0");
128 __desired_loop_time_sec = (float)__desired_loop_time_usec / 1000000.f;
131 __enable_looptime_warnings =
132 __config->
get_bool(
"/fawkes/mainapp/enable_looptime_warnings");
133 if(!__enable_looptime_warnings) {
134 __multi_logger->
log_debug(
name(),
"loop time warnings are disabled");
137 __enable_looptime_warnings =
true;
153 FawkesMainThread::destruct()
157 }
catch (CouldNotOpenFileException &e) {
158 if (e.get_errno() == EACCES) {
159 __multi_logger->
log_warn(
"FawkesMainThread",
"Cannot write to dump file, "
161 __multi_logger->
log_warn(
"FawkesMainThread",
"permission for file or "
163 __multi_logger->
log_warn(
"FawkesMainThread",
"usually happens if running "
165 __multi_logger->
log_warn(
"FawkesMainThread",
"installed Fawkes as non-root "
167 __multi_logger->
log_warn(
"FawkesMainThread",
"configuration changes to the "
169 __multi_logger->
log_warn(
"FawkesMainThread",
"database (set as non-default "
172 __multi_logger->
log_warn(
"FawkesMainThread",
"Failed to dump default "
173 "config (open), exception follows.");
174 __multi_logger->
log_warn(
"FawkesMainThread", e);
176 }
catch (Exception &e) {
177 __multi_logger->
log_warn(
"FawkesMainThread",
"Failed to dump default config, "
178 "exception follows.");
179 __multi_logger->
log_warn(
"FawkesMainThread", e);
182 if (__load_plugins) free(__load_plugins);
183 if (__default_plugin) free(__default_plugin);
189 delete __mainloop_barrier;
190 delete __mainloop_mutex;
200 __init_barrier =
new Barrier(2);
204 __init_barrier->
wait();
205 delete(__init_barrier);
213 if ( __load_plugins) {
215 __plugin_manager->
load(__load_plugins);
217 __multi_logger->
log_error(
"FawkesMainThread",
"Failed to load plugins %s, "
218 "exception follows", __load_plugins);
219 __multi_logger->
log_error(
"FawkesMainThread", e);
225 if (__default_plugin && (strcmp(
"default", __default_plugin) != 0)) {
226 __plugin_manager->
load(__default_plugin);
232 __multi_logger->
log_error(
"FawkesMainThread",
"Failed to load default "
233 "plugins, exception follows");
234 __multi_logger->
log_error(
"FawkesMainThread", e);
239 if (! __load_plugins) {
241 __plugin_manager->
load(
"default");
246 __multi_logger->
log_error(
"FawkesMainThread",
"Failed to load default "
247 "plugins, exception follows");
248 __multi_logger->
log_error(
"FawkesMainThread", e);
251 __multi_logger->
log_error(
"FawkesMainThread",
"Failed to load default "
252 "plugins, exception follows");
253 __multi_logger->
log_error(
"FawkesMainThread", e);
257 if (__init_barrier) __init_barrier->
wait();
264 __mainloop_mutex->
lock();
266 __mainloop_thread = mainloop_thread;
267 __mainloop_mutex->
unlock();
276 __multi_logger->
log_debug(
"FawkesMainThread",
"No timed threads exist, waiting");
279 __multi_logger->
log_debug(
"FawkesMainThread",
"Timed threads have been added, "
280 "running main loop now");
282 __multi_logger->
log_debug(
"FawkesMainThread",
"Waiting for timed threads interrupted");
287 __plugin_manager->
lock();
298 __mainloop_mutex->
lock();
300 if (unlikely(__mainloop_thread != NULL)) {
302 if (likely(__mainloop_thread != NULL)) {
303 __mainloop_thread->
wakeup(__mainloop_barrier);
304 __mainloop_barrier->
wait();
307 __multi_logger->
log_warn(
"FawkesMainThread", e);
321 __mainloop_mutex->
unlock();
326 __thread_manager->
try_recover(__recovered_threads);
327 if ( ! __recovered_threads.empty() ) {
330 if(__enable_looptime_warnings) {
331 if ( __recovered_threads.size() == 1 ) {
332 __multi_logger->
log_warn(
"FawkesMainThread",
"The thread %s could be "
333 "recovered and resumes normal operation",
334 __recovered_threads.front().c_str());
337 for (std::list<std::string>::iterator i = __recovered_threads.begin();
338 i != __recovered_threads.end(); ++i) {
342 __multi_logger->
log_warn(
"FawkesMainThread",
"The following threads could be "
343 "recovered and resumed normal operation: %s", s.c_str());
346 __recovered_threads.clear();
349 if (__desired_loop_time_sec > 0) {
351 float loop_time = *__loop_end - __loop_start;
352 if(__enable_looptime_warnings) {
355 if (loop_time > 1.1 * __desired_loop_time_sec) {
356 __multi_logger->
log_warn(
"FawkesMainThread",
"Loop time exceeded, "
357 "desired: %f sec (%u usec), actual: %f sec",
358 __desired_loop_time_sec, __desired_loop_time_usec,
364 __plugin_manager->
unlock();
372 __multi_logger->
log_warn(
"FawkesMainThread",
373 "Exception caught while executing default main "
375 __multi_logger->
log_warn(
"FawkesMainThread", e);
376 }
catch (std::exception &e) {
377 __multi_logger->
log_warn(
"FawkesMainThread",
378 "STL Exception caught while executing default main "
379 "loop, ignoring. (what: %s)", e.what());
392 return __multi_logger;
408 __init_mutex =
new Mutex();
409 __init_running =
true;
411 __sigint_running =
false;
412 __register_signals = register_signals;
416 if (__register_signals) {
427 if (__register_signals) {
439 __init_mutex->lock();
440 __init_running =
false;
441 if ( ! __init_quit ) {
443 __fmt->logger()->log_info(
"FawkesMainThread",
"Fawkes %s startup complete",
444 FAWKES_VERSION_STRING);
445 __init_mutex->unlock();
448 __init_mutex->unlock();
458 if ((signum == SIGINT) && ! __sigint_running) {
460 if (__init_running) {
465 __sigint_running =
true;
467 }
else if (signum == SIGALRM) {
470 printf(
"\nFawkes shutdown and finalization procedure still running.\n"
471 "Hit Ctrl-C again to force immediate exit.\n\n");
473 }
else if ((signum == SIGTERM) || __sigint_running) {