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) {
void full_start()
Start the thread and wait until once() completes.
act thread (motor module etc.)
void interrupt()
Interrupt the barrier.
static Clock * instance()
Clock initializer.
sensor data preparation thread, convert acquired data to usable format
virtual void log_error(const char *component, const char *format,...)
Log error message.
Time & stamp_systime()
Set this time to the current system time.
Configuration storage using SQLite.
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
void unlock()
Unlock the mutex.
virtual void wait()
Wait for other threads.
This exception is thrown if the requested plugin could not be loaded.
A class for handling time.
thread cannot be cancelled
virtual bool timed_threads_exist()
Check if any timed threads exist.
Thread class encapsulation of pthreads.
skill thread (skill module)
sensor data processing thread
static void set_cancel_state(CancelState new_state, CancelState *old_state=0)
Set the cancel state of the current thread.
virtual void loop()
Code to execute in the thread.
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
bool wait(unsigned int timeout_sec, unsigned int timeout_nanosec)
Wait for other threads.
void wait_systime()
Wait until minimum loop time has been reached in real time.
void try_dump()
Try to dump default configuration.
void lock()
Lock plugin manager.
std::string plugin_name() const
Get name of plugin which failed to load.
Log through multiple loggers.
Mutex * loopinterrupt_antistarve_mutex
Mutex to avoid starvation when trying to lock loop_mutex.
virtual void wait_for_timed_threads()
Wait for timed threads.
virtual ~FawkesMainThread()
Destructor.
void wakeup()
Wake up thread.
Base application thread manager.
Base class for exceptions in Fawkes.
void load(const char *plugin_list)
Load plugin.
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Runner(FawkesMainThread *fmt, bool register_signals=true)
Constructor.
static SignalHandler * register_handler(int signum, SignalHandler *handler)
Register a SignalHandler for a signal.
The current system call has been interrupted (for instance by a signal).
const char * name() const
Get name of thread.
MultiLogger * logger() const
Get logger.
virtual void log_info(const char *component, const char *format,...)
Log informational message.
void mark_start()
Mark start of loop.
void test_cancel()
Set cancellation point.
static void unregister_handler(int signum)
Unregister a SignalHandler for a signal.
void run()
Run main thread.
virtual void set_mainloop_thread(Thread *mainloop_thread)
Set a new main loop.
void yield()
Yield the processor to another thread or process.
void handle_signal(int signum)
Handle signals.
virtual void try_recover(std::list< std::string > &recovered_threads)
Try to recover threads.
void lock()
Lock this mutex.
void unlock()
Unlock plugin manager.
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
Mutex mutual exclusion lock.
Fawkes default main thread.
void exit()
Exit the thread.
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
void start(bool wait=true)
Call this method to start the thread.
sensor acquisition thread, acquire data from sensor
virtual void once()
Execute an action exactly once.