OW_StackTrace.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00035 #include "OW_config.h"
00036 #include "OW_StackTrace.hpp"
00037 
00038 #ifdef OW_WIN32
00039 #include <iostream>  // for cerr
00040 namespace OW_NAMESPACE
00041 {
00042 using std::cerr;
00043 using std::endl;
00044 void StackTrace::printStackTrace()
00045 {
00046    cerr << "StackTrace::printStackTrace not implemented yet" << endl;
00047 }
00048 }
00049 #else
00050 
00051 #include "OW_Exec.hpp"
00052 #include "OW_UnnamedPipe.hpp"
00053 #include "OW_Format.hpp"
00054 #include "OW_Array.hpp"
00055 #include <fstream>
00056 #include <iostream>  // for cerr
00057 
00058 #if defined(OW_HAVE_BACKTRACE)
00059 #include <execinfo.h>
00060 #endif
00061 
00062 #if defined(OW_HAVE_CXXABI_H)
00063 #include <cxxabi.h>
00064 #endif
00065 
00066 #ifdef OW_HAVE_UNISTD_H
00067 extern "C"
00068 {
00069 #include <unistd.h> // for getpid()
00070 }
00071 #endif
00072 
00073 namespace OW_NAMESPACE
00074 {
00075 
00076 using std::ifstream;
00077 using std::ofstream;
00078 using std::flush;
00079 
00080 #ifndef OW_DEFAULT_GDB_PATH
00081 #define OW_DEFAULT_GDB_PATH "/usr/bin/gdb"
00082 #endif
00083 
00084 // static
00085 void StackTrace::printStackTrace()
00086 {
00087    if (getenv("OW_STACKTRACE"))
00088    {
00089       // if we have the GNU backtrace functions we use them.  They don't give
00090       // as good information as gdb does, but they are orders of magnitude
00091       // faster!
00092 #ifdef OW_HAVE_BACKTRACE
00093       void *array[200];
00094       
00095       size_t size = backtrace (array, 200);
00096       char **strings = backtrace_symbols (array, size);
00097       
00098       String bt;
00099       
00100       size_t i;
00101       for (i = 0; i < size; i++)
00102       {
00103 #if defined(OW_HAVE_CXXABI_H)
00104          bt += strings[i];
00105          int status;
00106          // extract the identifier from strings[i].  It's inside of parens.
00107          char* firstparen = ::strchr(strings[i], '(');
00108          char* lastparen = ::strchr(strings[i], '+');
00109          if (firstparen != 0 && lastparen != 0 && firstparen < lastparen)
00110          {
00111             bt += ": ";
00112             *lastparen = '\0';
00113             char* realname = abi::__cxa_demangle(firstparen+1, 0, 0, &status);
00114             bt += realname;
00115             free(realname);
00116          }
00117 #else
00118          bt += strings[i];
00119 #endif
00120          bt += "\n";
00121       }
00122       
00123       free (strings);
00124       
00125       std::cerr << bt << std::endl;
00126 #else
00127       ifstream file(OW_DEFAULT_GDB_PATH);
00128       if (file)
00129       {
00130          file.close();
00131          String scriptName("/tmp/owgdb-");
00132          String outputName("/tmp/owgdbout-");
00133          // TODO: don't use getppid, get it from somewhere else!
00134          outputName += String(UInt32(::getpid()));
00135          scriptName += String(UInt32(::getpid())) + ".sh";
00136          String exeName("/proc/");
00137          exeName += String(UInt32(::getpid())) + "/exe";
00138          
00139          ofstream scriptFile(scriptName.c_str(), std::ios::out);
00140          scriptFile << "#!/bin/sh\n"
00141             << "gdb " << exeName << " " << ::getpid() << " << EOS > " << outputName << " 2>&1\n"
00142 // doesn't work with gdb 5.1           << "thread apply all bt\n"
00143             << "bt\n"
00144             << "detach\n"
00145             << "q\n"
00146             << "EOS\n" << flush;
00147          scriptFile.close();
00148          Array<String> command;
00149          command.push_back( "/bin/sh" );
00150          command.push_back( scriptName );
00151          Exec::safeSystem(command);
00152          ifstream outputFile(outputName.c_str(), std::ios::in);
00153          String output;
00154          while (outputFile)
00155          {
00156             output += String::getLine(outputFile) + "\n";
00157          }
00158          outputFile.close();
00159          unlink(outputName.c_str());
00160          unlink(scriptName.c_str());
00161          std::cerr << output << std::endl;
00162       }
00163 #endif
00164    }
00165 }
00166 
00167 } // end namespace OW_NAMESPACE
00168 
00169 #endif   // ifdef OW_WIN32

Generated on Thu Feb 9 08:48:16 2006 for openwbem by  doxygen 1.4.6