FixedAlloc::~FixedAlloc() { // Free all of the blocks while (m_firstBlock) { #ifdef MEMORY_INFO if(m_firstBlock->numAlloc > 0) { // go through every memory location, if the fourth 4 bytes cast as // an integer isn't 0xedededed then its allocated space and the integer is // an index into the stack trace table, the first 4 bytes will contain // the freelist pointer for free'd items (which is why the trace index is // stored in the second 4) // first 4 bytes - free list pointer // 2nd 4 bytes - alloc stack trace // 3rd 4 bytes - free stack trace // 4th 4 bytes - 0xedededed if freed correctly unsigned int *mem = (unsigned int*) m_firstBlock->items; unsigned int itemNum = 0; while(itemNum++ < m_itemsPerBlock) { unsigned int fourthInt = *(mem+3); if(fourthInt != 0xedededed) { GCDebugMsg(false, "Leaked %d byte item. Addr: 0x%x\n", GetItemSize(), mem+2); PrintStackTraceByIndex(*(mem+1)); } mem += (m_itemSize / sizeof(int)); } GCAssert(false); } // go through every item on the free list and make sure it wasn't written to // after being poisoned. void *item = m_firstBlock->firstFree; while(item) { #ifdef MMGC_64BIT for(int i=3, n=(m_firstBlock->size>>2)-3; i<n; i++) #else for(int i=3, n=(m_firstBlock->size>>2)-1; i<n; i++) #endif { unsigned int data = ((int*)item)[i]; if(data != 0xedededed) { GCDebugMsg(false, "Object 0x%x was written to after it was deleted, allocation trace:"); PrintStackTrace((int*)item+2); GCDebugMsg(false, "Deletion trace:"); PrintStackTrace((int*)item+3); GCDebugMsg(true, "Deleted item write violation!"); } } // next free item item = *((void**)item); } #endif FreeChunk(m_firstBlock); } }
/** This function gets called just before the "program executed an illegal instruction and will be terminated" or similar. Its purpose is to create the crashdump using the dbghlp DLLs */ static LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_ExceptionInfo) { char * newStack = &g_ExceptionStack[sizeof(g_ExceptionStack) - 1]; char * oldStack; // Use the substitute stack: // This code is the reason why we don't support 64-bit (yet) _asm { mov oldStack, esp mov esp, newStack } MINIDUMP_EXCEPTION_INFORMATION ExcInformation; ExcInformation.ThreadId = GetCurrentThreadId(); ExcInformation.ExceptionPointers = a_ExceptionInfo; ExcInformation.ClientPointers = 0; // Write the dump file: HANDLE dumpFile = CreateFile(g_DumpFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); g_WriteMiniDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, g_DumpFlags, (a_ExceptionInfo) ? &ExcInformation : nullptr, nullptr, nullptr); CloseHandle(dumpFile); // Print the stack trace for the basic debugging: PrintStackTrace(); // Revert to old stack: _asm { mov esp, oldStack } return 0; }
/* * @unimplemented */ LONG NTAPI RtlUnhandledExceptionFilter(IN struct _EXCEPTION_POINTERS* ExceptionInfo) { /* This is used by the security cookie checks, and also called externally */ UNIMPLEMENTED; PrintStackTrace(ExceptionInfo); return ERROR_CALL_NOT_IMPLEMENTED; }
CString GetStackTrace(HANDLE process, HANDLE thread, DWORD exCode, const CString& imageFile, LPVOID imageBase, DWORD imageSize) { std::ostringstream log; log << "Exception code 0x" << std::hex << exCode << std::endl; #ifdef _WIN64 // IS the process a 64-bit one, or a 32-bit one running under WOW (Windows On Windows)? BOOL isWow64 = FALSE; if (::IsWow64Process(process,&isWow64)) { if (isWow64) { WOW64_CONTEXT context = { 0 }; context.ContextFlags = CONTEXT_FULL; if (::Wow64GetThreadContext(thread,&context)) { PrintStackTrace(process,thread,imageFile,imageBase,imageSize, IMAGE_FILE_MACHINE_I386,context.Eip,context.Ebp,context.Esp,&context,log); } } else { CONTEXT context = { 0 }; context.ContextFlags = CONTEXT_FULL; if (::GetThreadContext(thread,&context)) { PrintStackTrace(process,thread,imageFile,imageBase,imageSize, IMAGE_FILE_MACHINE_AMD64,context.Rip,context.Rbp,context.Rsp,&context,log); } } } #else CONTEXT context = { 0 }; context.ContextFlags = CONTEXT_FULL; if (::GetThreadContext(thread,&context)) { PrintStackTrace(process,thread,imageFile,imageBase,imageSize, IMAGE_FILE_MACHINE_I386,context.Eip,context.Ebp,context.Esp,&context,log); } #endif return CString(log.str().c_str()); }
static void NonCtrlHandler(int a_Signal) { LOGD("Terminate event raised from std::signal"); cRoot::Get()->QueueExecuteConsoleCommand("stop"); switch (a_Signal) { case SIGSEGV: { std::signal(SIGSEGV, SIG_DFL); LOGERROR(" D: | Cuberite has encountered an error and needs to close"); LOGERROR("Details | SIGSEGV: Segmentation fault"); #ifdef BUILD_ID LOGERROR("Cuberite " BUILD_SERIES_NAME " build id: " BUILD_ID); LOGERROR("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME); #endif PrintStackTrace(); abort(); } case SIGABRT: #ifdef SIGABRT_COMPAT case SIGABRT_COMPAT: #endif { std::signal(a_Signal, SIG_DFL); LOGERROR(" D: | Cuberite has encountered an error and needs to close"); LOGERROR("Details | SIGABRT: Server self-terminated due to an internal fault"); #ifdef BUILD_ID LOGERROR("Cuberite " BUILD_SERIES_NAME " build id: " BUILD_ID); LOGERROR("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME); #endif PrintStackTrace(); abort(); } case SIGINT: case SIGTERM: { std::signal(a_Signal, SIG_IGN); // Server is shutting down, wait for it... break; } default: break; } }
void ExtendedLogger::Log(LogLevelType level, CArrRef stackTrace, bool escape /* = true */, bool escapeMore /* = false */) { assert(!escapeMore || escape); ThreadData *threadData = s_threadData.get(); if (++threadData->message > MaxMessagesPerRequest && MaxMessagesPerRequest >= 0) { return; } if (stackTrace.isNull()) return; if (UseLogFile) { FILE *f = Output ? Output : GetStandardOut(level); PrintStackTrace(f, stackTrace, escape, escapeMore); FILE *tf = threadData->log; if (tf) { PrintStackTrace(tf, stackTrace, escape, escapeMore); } } }
void ExtendedLogger::Log(bool err, CArrRef stackTrace, bool escape /* = true */, bool escapeMore /* = false */) { ASSERT(!escapeMore || escape); ThreadData *threadData = s_threadData.get(); if (++threadData->message > MaxMessagesPerRequest && MaxMessagesPerRequest >= 0) { return; } if (stackTrace.isNull()) return; // TODO Should we also send the stacktrace to LogAggregator? if (UseLogFile) { FILE *f = Output ? Output : (err ? stderr : stdout); PrintStackTrace(f, stackTrace, escape, escapeMore); FILE *tf = threadData->log; if (tf) { PrintStackTrace(tf, stackTrace, escape, escapeMore); } } }
static void CrashSignalHandler(int sig) { // Uninstall this handler, to avoid the possibility of an infinite regress signal(SIGSEGV, SIG_DFL); signal(SIGBUS, SIG_DFL); signal(SIGILL, SIG_DFL); signal(SIGABRT, SIG_DFL); signal(SIGFPE, SIG_DFL); printf("MUSCLE CrashSignalHandler called with signal %i... I'm going to print a stack trace, then kill the process.\n", sig); PrintStackTrace(); printf("Crashed MUSCLE process aborting now.... bye!\n"); fflush(stdout); abort(); }
/* eval(source) */ int DuckEval(int argument_count, void* data) { L_TOKEN* lexing; SYNTAX_TREE* ast; char* buffer; int error = 0; VALUE argument = GetRecord("source", gCurrentContext); gLastExpression.type = VAL_NIL; gLastExpression.data.primitive = 0; CLOSURE* currentContext; currentContext = gCurrentContext; int prev_line_error = line_error; SYNTAX_TREE* prev_failed_production = failed_production; // if (gCurrentContext->parent) gCurrentContext = gCurrentContext->parent; gCurrentContext = gGlobalContext; if (argument.type == VAL_STRING) { lexing = LexSourceBuffer(argument.data.string, &buffer, CONTEXT_FREE_GRAMMAR); if (lexing == NULL) { printf("Error lexing source or empty source string.\n"); FreeLexing(lexing, buffer); return 1; } ast = ParseSource(lexing, PARSE_TABLE, CONTEXT_FREE_GRAMMAR); if (ast == NULL) { printf("Error parsing source.\n"); FreeLexing(lexing, buffer); return 1; } /* ReduceProgramAST(&ast); */ error = InterpretNode(ast); if (error) { printf("%s\n", ErrorMessage(error)); PrintStackTrace(); FreeLexing(lexing, buffer); FreeParseTree(ast); ClearCallStack(&gStackTrace); line_error = prev_line_error; failed_production = prev_failed_production; return 1; } /* sanitize last expression for use in program */ //gLastExpression = ReallocStrings(gLastExpression); /* free lexing and parse tree */ //FreeLexing(lexing, buffer); //FreeParseTree(ast); GCAddLexing(lexing, buffer); GCAddParseTree(ast); } gCurrentContext = currentContext; return error; }