00001 /*************************************************************************** 00002 tag: Peter Soetens Mon May 10 19:10:29 CEST 2004 startstop.cxx 00003 00004 startstop.cxx - description 00005 ------------------- 00006 begin : Mon May 10 2004 00007 copyright : (C) 2004 Peter Soetens 00008 email : peter.soetens@mech.kuleuven.ac.be 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 00035 * * 00036 ***************************************************************************/ 00045 #include "../rtt-config.h" 00046 #include <os/startstop.h> 00047 #include "os/MainThread.hpp" 00048 #include "os/StartStopManager.hpp" 00049 #include "../internal/GlobalEngine.hpp" 00050 #include "../types/GlobalsRepository.hpp" 00051 #include "../types/TypekitRepository.hpp" 00052 00053 #ifdef OROPKG_OS_THREAD_SCOPE 00054 # include <boost/scoped_ptr.hpp> 00055 # include "../extras/dev/DigitalOutInterface.hpp" 00056 using namespace RTT; 00057 #endif 00058 00059 #ifdef OS_HAVE_IOSTREAM 00060 #include <iostream> 00061 using namespace std; 00062 #else 00063 #include <cstdio> 00064 #endif 00065 00066 #include "../Logger.hpp" 00067 #include "TimeService.hpp" 00068 00069 using namespace RTT; 00070 using namespace RTT::os; 00071 00072 static int os_argc_arg; 00073 static char** os_argv_arg; 00074 00075 int __os_init(int argc, char** argv ) 00076 { 00077 #ifdef OS_HAVE_MANUAL_CRT 00078 DO_GLOBAL_CTORS(); 00079 #endif 00080 00081 os_argc_arg = argc; 00082 os_argv_arg = argv; 00083 00084 os::MainThread::Instance(); 00085 Logger::log() << Logger::Debug << "MainThread started." << Logger::endl; 00086 00087 Logger::log() << Logger::Debug << "Starting StartStopManager." << Logger::endl; 00088 int ret = os::StartStopManager::Instance()->start() ? 0 : 1; 00089 00090 #ifdef OROPKG_OS_THREAD_SCOPE 00091 unsigned int bit = 0; 00092 00093 boost::scoped_ptr<DigitalOutInterface> pp; 00094 DigitalOutInterface* d = 0; 00095 // this is the device users can use across all threads to control the 00096 // scope's output. 00097 if ( DigitalOutInterface::nameserver.getObject("ThreadScope") ) 00098 d = DigitalOutInterface::nameserver.getObject("ThreadScope"); 00099 else 00100 Logger::log() << Logger::Error<< "Failed to find 'ThreadScope' object in DigitalOutInterface::nameserver." << Logger::endl; 00101 if ( d ) { 00102 Logger::log() << Logger::Info << "ThreadScope : main thread toggles bit "<< bit << Logger::endl; 00103 d->switchOn( bit ); 00104 } 00105 #endif 00106 return ret; 00107 } 00108 00109 int __os_main_argc(void) { 00110 return os_argc_arg; 00111 } 00112 char** __os_main_argv(void) { 00113 return os_argv_arg; 00114 } 00115 00116 void __os_printFailure(const char* prog) 00117 { 00118 #ifdef OS_HAVE_IOSTREAM 00119 cerr <<endl<< " Orocos has detected an uncaught C++ exception"<<endl; 00120 cerr << " in the ORO_main() function."<<endl; 00121 cerr << " You might have called a function which throws"<<endl; 00122 cerr << " without a try {} catch {} block."<< endl << endl; 00123 cerr << "To Debug this situation, issue the following command:"<<endl<<endl; 00124 cerr << " valgrind -v --num-callers=16 "<< prog <<" [options...] --nocatch" << endl; 00125 cerr << "Which will show where the exception occured."<<endl; 00126 cerr << " ( Change num-callers for more/less detail."<<endl; 00127 cerr << " Also, compiling orocos and your program with"<<endl; 00128 cerr << " -g adds more usefull information. )"<<endl<<endl; 00129 #else 00130 printf("Orocos intercepted an uncaught C++ exception\n"); 00131 #endif 00132 00133 } 00134 00135 void __os_printException(const char* prog, std::exception& arg) 00136 { 00137 #ifdef OS_HAVE_IOSTREAM 00138 cerr << endl<<" Caught std::exception." << endl << " what(): " << arg.what() <<endl; 00139 #endif 00140 __os_printFailure(prog); 00141 } 00142 00143 const char* oro_catchflag = "--nocatch"; 00144 const char* oro_catchflag2 = "--no-catch"; 00145 00146 int __os_checkException(int& argc, char** argv) 00147 { 00148 bool dotry = true; 00149 // look for --nocatch/--no-catch flag : 00150 for( int i=1; i < argc; ++i) 00151 if ( strncmp(oro_catchflag, argv[i], strlen(oro_catchflag) ) == 0 00152 || strncmp(oro_catchflag2, argv[i], strlen(oro_catchflag2) ) == 0 ) { 00153 // if --no-catch was given last, remove it from the argc. 00154 if ( i == argc-1) 00155 --argc; 00156 dotry = false; 00157 } 00158 00159 return dotry; 00160 } 00161 00162 void __os_exit(void) 00163 { 00164 #ifdef OROPKG_OS_THREAD_SCOPE 00165 if (d) 00166 d->switchOff(bit); 00167 #endif 00168 00169 internal::GlobalEngine::Release(); 00170 00171 types::GlobalsRepository::Release(); 00172 00173 types::TypekitRepository::Release(); 00174 00175 Logger::log() << Logger::Debug << "Stopping StartStopManager." << Logger::endl; 00176 os::StartStopManager::Instance()->stop(); 00177 os::StartStopManager::Release(); 00178 00179 // This should be the (one but) last message to be logged : 00180 Logger::log() << Logger::Debug << "Stopping MainThread." << Logger::endl; 00181 00182 // Stop logging 00183 Logger::Release(); 00184 00185 // Stop TimeService if present. 00186 TimeService::Release(); 00187 00188 // Stop Main Thread 00189 os::MainThread::Release(); 00190 00191 #ifdef OS_HAVE_MANUAL_CRT 00192 DO_GLOBAL_DTORS(); 00193 #endif 00194 }