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 static os::StartStopManager* initM; 00072 00073 static int os_argc_arg; 00074 static char** os_argv_arg; 00075 00076 int __os_init(int argc, char** argv ) 00077 { 00078 #ifdef OS_HAVE_MANUAL_CRT 00079 DO_GLOBAL_CTORS(); 00080 #endif 00081 00082 os_argc_arg = argc; 00083 os_argv_arg = argv; 00084 00085 os::MainThread::Instance(); 00086 Logger::log() << Logger::Debug << "MainThread started." << Logger::endl; 00087 00088 Logger::log() << Logger::Debug << "Starting StartStopManager." << Logger::endl; 00089 initM = os::StartStopManager::Instance(); 00090 int ret = initM->start() ? 0 : 1; 00091 00092 #ifdef OROPKG_OS_THREAD_SCOPE 00093 unsigned int bit = 0; 00094 00095 boost::scoped_ptr<DigitalOutInterface> pp; 00096 DigitalOutInterface* d = 0; 00097 // this is the device users can use across all threads to control the 00098 // scope's output. 00099 if ( DigitalOutInterface::nameserver.getObject("ThreadScope") ) 00100 d = DigitalOutInterface::nameserver.getObject("ThreadScope"); 00101 else 00102 Logger::log() << Logger::Error<< "Failed to find 'ThreadScope' object in DigitalOutInterface::nameserver." << Logger::endl; 00103 if ( d ) { 00104 Logger::log() << Logger::Info << "ThreadScope : main thread toggles bit "<< bit << Logger::endl; 00105 d->switchOn( bit ); 00106 } 00107 #endif 00108 return ret; 00109 } 00110 00111 int __os_main_argc(void) { 00112 return os_argc_arg; 00113 } 00114 char** __os_main_argv(void) { 00115 return os_argv_arg; 00116 } 00117 00118 void __os_printFailure(const char* prog) 00119 { 00120 #ifdef OS_HAVE_IOSTREAM 00121 cerr <<endl<< " Orocos has detected an uncaught C++ exception"<<endl; 00122 cerr << " in the ORO_main() function."<<endl; 00123 cerr << " You might have called a function which throws"<<endl; 00124 cerr << " without a try {} catch {} block."<< endl << endl; 00125 cerr << "To Debug this situation, issue the following command:"<<endl<<endl; 00126 cerr << " valgrind -v --num-callers=16 "<< prog <<" [options...] --nocatch" << endl; 00127 cerr << "Which will show where the exception occured."<<endl; 00128 cerr << " ( Change num-callers for more/less detail."<<endl; 00129 cerr << " Also, compiling orocos and your program with"<<endl; 00130 cerr << " -g adds more usefull information. )"<<endl<<endl; 00131 #else 00132 printf("Orocos intercepted an uncaught C++ exception\n"); 00133 #endif 00134 00135 } 00136 00137 void __os_printException(const char* prog, std::exception& arg) 00138 { 00139 #ifdef OS_HAVE_IOSTREAM 00140 cerr << endl<<" Caught std::exception." << endl << " what(): " << arg.what() <<endl; 00141 #endif 00142 __os_printFailure(prog); 00143 } 00144 00145 const char* oro_catchflag = "--nocatch"; 00146 const char* oro_catchflag2 = "--no-catch"; 00147 00148 int __os_checkException(int& argc, char** argv) 00149 { 00150 bool dotry = true; 00151 // look for --nocatch/--no-catch flag : 00152 for( int i=1; i < argc; ++i) 00153 if ( strncmp(oro_catchflag, argv[i], strlen(oro_catchflag) ) == 0 00154 || strncmp(oro_catchflag2, argv[i], strlen(oro_catchflag2) ) == 0 ) { 00155 // if --no-catch was given last, remove it from the argc. 00156 if ( i == argc-1) 00157 --argc; 00158 dotry = false; 00159 } 00160 00161 return dotry; 00162 } 00163 00164 void __os_exit(void) 00165 { 00166 #ifdef OROPKG_OS_THREAD_SCOPE 00167 if (d) 00168 d->switchOff(bit); 00169 #endif 00170 00171 internal::GlobalEngine::Release(); 00172 00173 types::GlobalsRepository::Release(); 00174 00175 types::TypekitRepository::Release(); 00176 00177 Logger::log() << Logger::Debug << "Stopping StartStopManager." << Logger::endl; 00178 initM->stop(); 00179 os::StartStopManager::Release(); 00180 00181 // This should be the (one but) last message to be logged : 00182 Logger::log() << Logger::Debug << "Stopping MainThread." << Logger::endl; 00183 00184 // Stop logging 00185 Logger::Release(); 00186 00187 // Stop TimeService if present. 00188 TimeService::Release(); 00189 00190 // Stop Main Thread 00191 os::MainThread::Release(); 00192 00193 #ifdef OS_HAVE_MANUAL_CRT 00194 DO_GLOBAL_DTORS(); 00195 #endif 00196 }