Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

vul_debug.cxx

Go to the documentation of this file.
00001 // This is core/vul/vul_debug.cxx
00002 
00003 //: \file
00004 //  \brief Get debug related information like core dumps, and stack traces
00005 //  \author Ian Scott
00006 
00007 #include "vul_debug.h"
00008 #include <vcl_iostream.h>
00009 #include <vxl_config.h>
00010 #include <vcl_new.h>
00011 #include <vcl_cstdlib.h>
00012 
00013 #ifdef _WIN32
00014 
00015 #if VXL_HAS_DBGHELP_H
00016 
00017 #define NOATOM
00018 #define NOGDI
00019 #define NOGDICAPMASKS
00020 #define NOMETAFILE
00021 #define NOMINMAX
00022 #define NOMSG
00023 #define NOOPENFILE
00024 #define NORASTEROPS
00025 #define NOSCROLL
00026 #define NOSOUND
00027 #define NOSYSMETRICS
00028 #define NOTEXTMETRIC
00029 #define NOWH
00030 #define NOCOMM
00031 #define NOKANJI
00032 #define NOCRYPT
00033 #define NOMCX
00034 #include <windows.h>
00035 #include <DbgHelp.h>
00036 #include <vcl_cstdio.h>
00037 #pragma comment (lib, "dbghelp")
00038 
00039 static void vul_debug_core_dump_in_windows_seh(const char * filename,
00040                                                EXCEPTION_POINTERS* pep)
00041 {
00042   static char buffer[2048];
00043   static int count = 0;
00044   vcl_snprintf(buffer, sizeof(buffer), filename, count++);
00045   buffer[sizeof(buffer)-1]=0; // Just in case it is too long
00046 
00047   HANDLE hFile = CreateFile( buffer, GENERIC_READ | GENERIC_WRITE, 
00048     0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); 
00049 
00050   if ( ( hFile == NULL ) || ( hFile == INVALID_HANDLE_VALUE ) )
00051   {
00052     vcl_cerr << "WARNING: vul_debug_core_dump: Unable to create core dump file: " << filename << vcl_endl;
00053     return;
00054   }
00055 
00056   MINIDUMP_EXCEPTION_INFORMATION mdei; 
00057   mdei.ThreadId           = GetCurrentThreadId(); 
00058   mdei.ExceptionPointers  = pep; 
00059   mdei.ClientPointers     = FALSE; 
00060 
00061   if (! MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), 
00062     hFile, MiniDumpWithFullMemory, (pep != 0) ? &mdei : 0, 0, 0 ))
00063     vcl_cerr << "WARNING: vul_debug_core_dump: Unable to dump core: " << filename << vcl_endl;
00064 
00065   CloseHandle( hFile ); 
00066 }
00067 
00068 void vul_debug_core_dump_in_windows_seh(const char * filename,
00069                                         void* pep)
00070 {
00071   vul_debug_core_dump_in_windows_seh(filename, (EXCEPTION_POINTERS*)pep);
00072 }
00073 
00074 // Default builds don't set the correct compiler flags
00075 // but we don't want a warning.
00076 #pragma warning (disable: 4535)
00077 
00078 
00079 void vul_debug_core_dump(const char * filename)
00080 {
00081   _se_translator_function current = _set_se_translator(0);
00082 
00083   __try
00084   {
00085     RaiseException(0xe0000000,0,0,0);
00086   }
00087   __except(vul_debug_core_dump_in_windows_seh(filename, GetExceptionInformation()),1)
00088   {}
00089   _set_se_translator(current);
00090 }
00091 
00092 //: Windows structured exception code.
00093 unsigned vul_debug_windows_structured_exception::code() const
00094 {
00095   return static_cast<EXCEPTION_POINTERS*>(ex_ptr_)->ExceptionRecord->ExceptionCode;
00096 }
00097 
00098 //: Related execution address.
00099 void *vul_debug_windows_structured_exception::address() const
00100 {
00101   return static_cast<EXCEPTION_POINTERS*>(ex_ptr_)->ExceptionRecord->ExceptionAddress;
00102 }
00103 
00104 const char *vul_debug_windows_structured_exception::what() const throw()
00105 {
00106   static char buf[100];
00107   vcl_sprintf(buf, "Caught Windows Structured Exception. Code %lx. Address %lx", code(), address());
00108   return buf;
00109 }
00110 
00111 static const char* se_coredump_filename = 0;
00112 
00113 void vul_debug_set_coredump_and_throw_on_windows_se_handler(
00114   unsigned code, EXCEPTION_POINTERS * ex_ptr)
00115 {
00116   vul_debug_core_dump_in_windows_seh(se_coredump_filename, ex_ptr);
00117 #ifdef VCL_HAS_EXCEPTIONS
00118   throw vul_debug_windows_structured_exception(ex_ptr);
00119 #else
00120   vcl_cerr << vul_debug_windows_structured_exception(ex_ptr).what();
00121   vcl_abort();
00122 #endif
00123 }
00124 
00125 
00126 //: Setup the system to core dump and throw a C++ exception on detection of a Structured Exception
00127 // \throws vul_debug_windows_structured_exception. 
00128 void vul_debug_set_coredump_and_throw_on_windows_se(const char * filename)
00129 {
00130   se_coredump_filename = filename;
00131   _set_se_translator(vul_debug_set_coredump_and_throw_on_windows_se_handler);
00132 }
00133 
00134 
00135 # else //VXL_HAS_DBGHELP_H
00136 
00137 void vul_debug_core_dump_in_windows_seh(const char *, void*)
00138 {
00139   vcl_cerr << "WARNING: vul_debug_core_dump_in_windows_seh: Unable to core dump\n";
00140 }
00141 
00142 void vul_debug_core_dump(const char *)
00143 {
00144   vcl_cerr << "WARNING: vul_debug_core_dump: Unable to core dump\n";
00145 }
00146 
00147 //: Windows structured exception code.
00148 unsigned vul_debug_windows_structured_exception::code() const
00149 {
00150   return 0;
00151 }
00152 
00153 //: Related execution address.
00154 void *vul_debug_windows_structured_exception::address() const
00155 {
00156   return 0;
00157 }
00158 
00159 const char *vul_debug_windows_structured_exception::what() const throw()
00160 {
00161   return "Caught Windows Exception on machine with old or no version of DbgHelp.";
00162 }
00163 
00164 
00165 //: Setup the system to core dump and throw a C++ exception on detection of a Structured Exception
00166 // \throws vul_debug_windows_structured_exception. 
00167 void vul_debug_set_coredump_and_throw_on_windows_se(const char * )
00168 {
00169   vcl_cerr << "WARNING: No DbgHelp.h on this platform - can't set SE Handler.\n";
00170 }
00171 
00172 # endif // VXL_HAS_DBGHELP_H
00173 
00174 
00175 #else // _WIN32 
00176 
00177 #include <vcl_string.h>
00178 #ifdef VXL_UNISTD_HAS_GETPID
00179 # include <unistd.h>
00180 #endif
00181 #include <vul/vul_sprintf.h>
00182 
00183 void vul_debug_core_dump(const char * filename)
00184 {
00185   static int count = 0;
00186 #ifdef VXL_UNISTD_HAS_GETPID
00187   vcl_string syscall = "gcore -o ";
00188   syscall += vul_sprintf(filename, count++);
00189   syscall += vul_sprintf(" %d", getpid());
00190   if (system(syscall.c_str())==0) return;
00191   syscall = "gcore -s -c ";
00192   syscall += filename;
00193   syscall += vul_sprintf(" %d", getpid());
00194   if (system(syscall.c_str())==0) return;
00195 #endif
00196   vcl_cerr << "WARNING: vul_debug_core_dump: Unable to core dump\n";
00197 }
00198 // For a more reliable way of dunping core try forking and sending a SIGSTOP to the child.
00199 // see http://kasperd.net/~kasperd/comp.os.linux.development.faq
00200 
00201 //: Setup the system to core dump and throw a C++ exception on detection of a Structured Exception
00202 // \throws vul_debug_windows_structured_exception. 
00203 void vul_debug_set_coredump_and_throw_on_windows_se(const char * filename)
00204 {
00205 // Do nothing on non-windows box.
00206 }
00207 
00208 #endif // _WIN32
00209 
00210 
00211 static const char* out_out_memory_coredump_filename = 0;
00212 
00213 void 
00214 #ifdef _WIN32
00215   __cdecl
00216 #endif
00217   vul_debug_set_coredump_and_throw_on_out_of_memory_handler()
00218 {
00219   vul_debug_core_dump(out_out_memory_coredump_filename);
00220 #if VCL_HAS_EXCEPTIONS
00221   throw vcl_bad_alloc();
00222 #else
00223   vcl_cerr << "Out of Memory.\n";
00224   vcl_abort();
00225 #endif
00226 }
00227 
00228 //: Setup the system to core dump and throw a C++ exception on detection of out of memory.
00229 // The system will throw vcl_bad_alloc. 
00230 void vul_debug_set_coredump_and_throw_on_out_of_memory(const char * filename)
00231 {
00232   out_out_memory_coredump_filename = filename;
00233   vcl_set_new_handler(vul_debug_set_coredump_and_throw_on_out_of_memory_handler);
00234 }

Generated on Thu Jan 10 14:41:00 2008 for core/vul by  doxygen 1.4.4