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/config.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;
86 __mainloop_thread = NULL;
87 __mainloop_mutex =
new Mutex();
90 __load_plugins = NULL;
92 __load_plugins = strdup(load_plugins);
95 __default_plugin = NULL;
97 __default_plugin = strdup(default_plugin);
103 __loop_start =
new Time(__clock);
104 __loop_end =
new Time(__clock);
106 __max_thread_time_usec = __config->
get_uint(
"/fawkes/mainapp/max_thread_time");
108 __max_thread_time_usec = 30000;
109 __multi_logger->
log_info(
"FawkesMainApp",
110 "Maximum thread time not set, assuming 30ms.");
112 __max_thread_time_nanosec = __max_thread_time_usec * 1000;
116 __desired_loop_time_usec =
117 __config->
get_uint(
"/fawkes/mainapp/desired_loop_time");
118 if ( __desired_loop_time_usec > 0 ) {
119 __time_wait =
new TimeWait(__clock, __desired_loop_time_usec);
122 __desired_loop_time_usec = 0;
123 __multi_logger->
log_info(
"FawkesMainApp",
124 "Desired loop time not set, assuming 0");
127 __desired_loop_time_sec = (float)__desired_loop_time_usec / 1000000.f;
130 __enable_looptime_warnings =
131 __config->
get_bool(
"/fawkes/mainapp/enable_looptime_warnings");
132 if(!__enable_looptime_warnings) {
133 __multi_logger->
log_debug(
name(),
"loop time warnings are disabled");
136 __enable_looptime_warnings =
true;
152 FawkesMainThread::destruct()
158 __multi_logger->
log_warn(
"FawkesMainThread",
"Cannot write to dump file, " 160 __multi_logger->
log_warn(
"FawkesMainThread",
"permission for file or " 162 __multi_logger->
log_warn(
"FawkesMainThread",
"usually happens if running " 164 __multi_logger->
log_warn(
"FawkesMainThread",
"installed Fawkes as non-root " 166 __multi_logger->
log_warn(
"FawkesMainThread",
"configuration changes to the " 168 __multi_logger->
log_warn(
"FawkesMainThread",
"database (set as non-default " 171 __multi_logger->
log_warn(
"FawkesMainThread",
"Failed to dump default " 172 "config (open), exception follows.");
173 __multi_logger->
log_warn(
"FawkesMainThread", e);
176 __multi_logger->
log_warn(
"FawkesMainThread",
"Failed to dump default config, " 177 "exception follows.");
178 __multi_logger->
log_warn(
"FawkesMainThread", e);
181 if (__load_plugins) free(__load_plugins);
182 if (__default_plugin) free(__default_plugin);
188 delete __mainloop_barrier;
189 delete __mainloop_mutex;
199 __init_barrier =
new Barrier(2);
203 __init_barrier->
wait();
204 delete(__init_barrier);
212 if ( __load_plugins) {
214 __plugin_manager->
load(__load_plugins);
216 __multi_logger->
log_error(
"FawkesMainThread",
"Failed to load plugins %s, " 217 "exception follows", __load_plugins);
218 __multi_logger->
log_error(
"FawkesMainThread", e);
224 if (__default_plugin && (strcmp(
"default", __default_plugin) != 0)) {
225 __plugin_manager->
load(__default_plugin);
231 __multi_logger->
log_error(
"FawkesMainThread",
"Failed to load default " 232 "plugins, exception follows");
233 __multi_logger->
log_error(
"FawkesMainThread", e);
238 if (! __load_plugins) {
240 __plugin_manager->
load(
"default");
245 __multi_logger->
log_error(
"FawkesMainThread",
"Failed to load default " 246 "plugins, exception follows");
247 __multi_logger->
log_error(
"FawkesMainThread", e);
250 __multi_logger->
log_error(
"FawkesMainThread",
"Failed to load default " 251 "plugins, exception follows");
252 __multi_logger->
log_error(
"FawkesMainThread", e);
256 if (__init_barrier) __init_barrier->
wait();
263 __mainloop_mutex->
lock();
265 __mainloop_thread = mainloop_thread;
266 __mainloop_mutex->
unlock();
275 __multi_logger->
log_debug(
"FawkesMainThread",
"No timed threads exist, waiting");
278 __multi_logger->
log_debug(
"FawkesMainThread",
"Timed threads have been added, " 279 "running main loop now");
281 __multi_logger->
log_debug(
"FawkesMainThread",
"Waiting for timed threads interrupted");
286 __plugin_manager->
lock();
297 __mainloop_mutex->
lock();
299 if (unlikely(__mainloop_thread != NULL)) {
301 if (likely(__mainloop_thread != NULL)) {
302 __mainloop_thread->
wakeup(__mainloop_barrier);
303 __mainloop_barrier->
wait();
306 __multi_logger->
log_warn(
"FawkesMainThread", e);
320 __mainloop_mutex->
unlock();
325 __thread_manager->
try_recover(__recovered_threads);
326 if ( ! __recovered_threads.empty() ) {
329 if(__enable_looptime_warnings) {
330 if ( __recovered_threads.size() == 1 ) {
331 __multi_logger->
log_warn(
"FawkesMainThread",
"The thread %s could be " 332 "recovered and resumes normal operation",
333 __recovered_threads.front().c_str());
336 for (std::list<std::string>::iterator i = __recovered_threads.begin();
337 i != __recovered_threads.end(); ++i) {
341 __multi_logger->
log_warn(
"FawkesMainThread",
"The following threads could be " 342 "recovered and resumed normal operation: %s", s.c_str());
345 __recovered_threads.clear();
348 if (__desired_loop_time_sec > 0) {
350 float loop_time = *__loop_end - __loop_start;
351 if(__enable_looptime_warnings) {
354 if (loop_time > 1.1 * __desired_loop_time_sec) {
355 __multi_logger->
log_warn(
"FawkesMainThread",
"Loop time exceeded, " 356 "desired: %f sec (%u usec), actual: %f sec",
357 __desired_loop_time_sec, __desired_loop_time_usec,
363 __plugin_manager->
unlock();
371 __multi_logger->
log_warn(
"FawkesMainThread",
372 "Exception caught while executing default main " 374 __multi_logger->
log_warn(
"FawkesMainThread", e);
375 }
catch (std::exception &e) {
376 __multi_logger->
log_warn(
"FawkesMainThread",
377 "STL Exception caught while executing default main " 378 "loop, ignoring. (what: %s)", e.what());
391 return __multi_logger;
407 __init_mutex =
new Mutex();
408 __init_running =
true;
410 __sigint_running =
false;
411 __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.
virtual void try_dump()=0
Try to dump configuration.
File could not be opened.
act thread (motor module etc.)
int get_errno()
Get errno.
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.
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 lock()
Lock plugin manager.
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.
static void ignore(int signum)
Ignore a signal.
const char * name() const
Get name of thread.
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).
virtual void log_info(const char *component, const char *format,...)
Log informational message.
std::string plugin_name() const
Get name of plugin which failed to load.
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.
MultiLogger * logger() const
Get logger.
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.
Interface for configuration handling.
FawkesMainThread(Configuration *config, MultiLogger *multi_logger, ThreadManager *thread_manager, PluginManager *plugin_manager, const char *load_plugins, const char *default_plugin=0)
Constructor.
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.