24 #include <aspect/manager.h>
25 #include <baseapp/main_thread.h>
26 #include <config/config.h>
27 #include <core/exceptions/system.h>
28 #include <core/macros.h>
29 #include <core/threading/interruptible_barrier.h>
30 #include <core/threading/mutex_locker.h>
31 #include <core/version.h>
32 #include <plugin/loader.h>
33 #include <plugin/manager.h>
34 #include <utils/time/clock.h>
35 #include <utils/time/wait.h>
65 MultiLogger * multi_logger,
66 ThreadManager * thread_manager,
67 SyncPointManager *syncpoint_manager,
69 const char * load_plugins,
70 const char * default_plugin)
71 :
Thread(
"FawkesMainThread")
73 plugin_manager_ = plugin_manager;
74 thread_manager_ = thread_manager;
75 syncpoint_manager_ = syncpoint_manager;
76 multi_logger_ = multi_logger;
79 mainloop_thread_ = NULL;
80 mainloop_mutex_ =
new Mutex();
85 load_plugins_ = strdup(load_plugins);
88 default_plugin_ = NULL;
90 default_plugin_ = strdup(default_plugin);
96 loop_start_ =
new Time(clock_);
97 loop_end_ =
new Time(clock_);
99 max_thread_time_usec_ = config_->
get_uint(
"/fawkes/mainapp/max_thread_time");
101 max_thread_time_usec_ = 30000;
102 multi_logger_->
log_info(
"FawkesMainApp",
"Maximum thread time not set, assuming 30ms.");
104 max_thread_time_nanosec_ = max_thread_time_usec_ * 1000;
108 desired_loop_time_usec_ = config_->
get_uint(
"/fawkes/mainapp/desired_loop_time");
109 if (desired_loop_time_usec_ > 0) {
110 time_wait_ =
new TimeWait(clock_, desired_loop_time_usec_);
113 desired_loop_time_usec_ = 0;
114 multi_logger_->
log_info(
"FawkesMainApp",
"Desired loop time not set, assuming 0");
117 desired_loop_time_sec_ = (float)desired_loop_time_usec_ / 1000000.f;
120 enable_looptime_warnings_ = config_->
get_bool(
"/fawkes/mainapp/enable_looptime_warnings");
121 if (!enable_looptime_warnings_) {
122 multi_logger_->
log_debug(
name(),
"loop time warnings are disabled");
125 enable_looptime_warnings_ =
true;
139 FawkesMainThread::destruct()
145 multi_logger_->
log_warn(
"FawkesMainThread",
146 "Cannot write to dump file, "
148 multi_logger_->
log_warn(
"FawkesMainThread",
149 "permission for file or "
151 multi_logger_->
log_warn(
"FawkesMainThread",
152 "usually happens if running "
154 multi_logger_->
log_warn(
"FawkesMainThread",
155 "installed Fawkes as non-root "
157 multi_logger_->
log_warn(
"FawkesMainThread",
158 "configuration changes to the "
160 multi_logger_->
log_warn(
"FawkesMainThread",
161 "database (set as non-default "
164 multi_logger_->
log_warn(
"FawkesMainThread",
165 "Failed to dump default "
166 "config (open), exception follows.");
167 multi_logger_->
log_warn(
"FawkesMainThread", e);
170 multi_logger_->
log_warn(
"FawkesMainThread",
171 "Failed to dump default config, "
172 "exception follows.");
173 multi_logger_->
log_warn(
"FawkesMainThread", e);
179 free(default_plugin_);
185 delete mainloop_barrier_;
186 delete mainloop_mutex_;
196 init_barrier_ =
new Barrier(2);
200 init_barrier_->
wait();
201 delete (init_barrier_);
209 std::vector<BlockedTimingAspect::WakeupHook> hooks;
222 for (std::vector<BlockedTimingAspect::WakeupHook>::const_iterator it = hooks.begin();
225 syncpoints_start_hook_.push_back(syncpoint_manager_->
get_syncpoint(
227 syncpoints_start_hook_.back()->register_emitter(
"FawkesMainThread");
228 syncpoints_end_hook_.push_back(syncpoint_manager_->
get_syncpoint(
232 multi_logger_->
log_error(
"FawkesMainThread",
"Failed to acquire mainloop syncpoint");
239 plugin_manager_->
load(load_plugins_);
240 }
catch (Exception &e) {
241 multi_logger_->
log_error(
"FawkesMainThread",
242 "Failed to load plugins %s, "
245 multi_logger_->
log_error(
"FawkesMainThread", e);
251 if (default_plugin_ && (strcmp(
"default", default_plugin_) != 0)) {
252 plugin_manager_->
load(default_plugin_);
254 }
catch (PluginLoadException &e) {
255 if (e.plugin_name() != default_plugin_) {
258 multi_logger_->
log_error(
"FawkesMainThread",
259 "Failed to load default "
260 "plugins, exception follows");
261 multi_logger_->
log_error(
"FawkesMainThread", e);
266 if (!load_plugins_) {
268 plugin_manager_->
load(
"default");
269 }
catch (PluginLoadException &e) {
270 if (e.plugin_name() !=
"default") {
273 multi_logger_->
log_error(
"FawkesMainThread",
274 "Failed to load default "
275 "plugins, exception follows");
276 multi_logger_->
log_error(
"FawkesMainThread", e);
278 }
catch (Exception &e) {
279 multi_logger_->
log_error(
"FawkesMainThread",
280 "Failed to load default "
281 "plugins, exception follows");
282 multi_logger_->
log_error(
"FawkesMainThread", e);
287 init_barrier_->
wait();
294 mainloop_mutex_->
lock();
296 mainloop_thread_ = mainloop_thread;
297 mainloop_mutex_->
unlock();
305 multi_logger_->
log_debug(
"FawkesMainThread",
"No timed threads exist, waiting");
308 multi_logger_->
log_debug(
"FawkesMainThread",
309 "Timed threads have been added, "
310 "running main loop now");
312 multi_logger_->
log_debug(
"FawkesMainThread",
"Waiting for timed threads interrupted");
317 plugin_manager_->
lock();
328 mainloop_mutex_->
lock();
330 if (unlikely(mainloop_thread_ != NULL)) {
332 if (likely(mainloop_thread_ != NULL)) {
333 mainloop_thread_->
wakeup(mainloop_barrier_);
334 mainloop_barrier_->
wait();
336 }
catch (Exception &e) {
337 multi_logger_->
log_warn(
"FawkesMainThread", e);
340 uint num_hooks = syncpoints_start_hook_.size();
341 if (syncpoints_end_hook_.size() != num_hooks) {
344 "Hook syncpoints are not initialized properly, not waking up any threads!");
346 for (uint i = 0; i < num_hooks; i++) {
347 syncpoints_start_hook_[i]->emit(
"FawkesMainThread");
348 syncpoints_end_hook_[i]->reltime_wait_for_all(
"FawkesMainThread",
350 max_thread_time_nanosec_);
354 mainloop_mutex_->
unlock();
360 if (!recovered_threads_.empty()) {
363 if (enable_looptime_warnings_) {
364 if (recovered_threads_.size() == 1) {
365 multi_logger_->
log_warn(
"FawkesMainThread",
366 "The thread %s could be "
367 "recovered and resumes normal operation",
368 recovered_threads_.front().c_str());
371 for (std::list<std::string>::iterator i = recovered_threads_.begin();
372 i != recovered_threads_.end();
377 multi_logger_->
log_warn(
"FawkesMainThread",
378 "The following threads could be "
379 "recovered and resumed normal operation: %s",
383 recovered_threads_.clear();
386 if (desired_loop_time_sec_ > 0) {
388 float loop_time = *loop_end_ - loop_start_;
389 if (enable_looptime_warnings_) {
392 if (loop_time > 1.1 * desired_loop_time_sec_) {
393 multi_logger_->
log_warn(
"FawkesMainThread",
394 "Loop time exceeded, "
395 "desired: %f sec (%u usec), actual: %f sec",
396 desired_loop_time_sec_,
397 desired_loop_time_usec_,
403 plugin_manager_->
unlock();
410 }
catch (Exception &e) {
411 multi_logger_->
log_warn(
"FawkesMainThread",
412 "Exception caught while executing default main "
414 multi_logger_->
log_warn(
"FawkesMainThread", e);
415 }
catch (std::exception &e) {
416 multi_logger_->
log_warn(
"FawkesMainThread",
417 "STL Exception caught while executing default main "
418 "loop, ignoring. (what: %s)",
431 return multi_logger_;
447 init_mutex_ =
new Mutex();
448 init_running_ =
true;
450 sigint_running_ =
false;
451 register_signals_ = register_signals;
456 if (register_signals_) {
466 if (register_signals_) {
479 init_running_ =
false;
482 fmt_->logger()->log_info(
"FawkesMainThread",
483 "Fawkes %s startup complete",
484 FAWKES_VERSION_STRING);
485 init_mutex_->unlock();
488 init_mutex_->unlock();
498 if ((signum == SIGINT) && !sigint_running_) {
499 MutexLocker lock(init_mutex_);
505 sigint_running_ =
true;
507 }
else if (signum == SIGALRM) {
510 printf(
"\nFawkes shutdown and finalization procedure still running.\n"
511 "Hit Ctrl-C again to force immediate exit.\n\n");
513 }
else if ((signum == SIGTERM) || sigint_running_) {