From 5b757e536fedaf06cc27f977fa0fa0537f1ff4f0 Mon Sep 17 00:00:00 2001 From: janwas Date: Fri, 4 Jul 2008 18:02:54 +0000 Subject: [PATCH] fix: avoid reentering allocation hook if an error is raised within memory allocators This was SVN commit r6196. --- source/lib/sysdep/os/win/wdbg_sym.cpp | 48 +++++++++++++++++++-------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/source/lib/sysdep/os/win/wdbg_sym.cpp b/source/lib/sysdep/os/win/wdbg_sym.cpp index 3ef3b8ab8d..19930c99c9 100644 --- a/source/lib/sysdep/os/win/wdbg_sym.cpp +++ b/source/lib/sysdep/os/win/wdbg_sym.cpp @@ -1238,28 +1238,48 @@ static LibError dump_sym_function_type(DWORD UNUSED(type_id), const u8* p, DumpS // clutter a bit and prevents infinite recursion for cyclical references // (e.g. via struct S { S* p; } s; s.p = &s;) -typedef std::set PtrSet; -static PtrSet* already_visited_ptrs; - // allocated on-demand by ptr_already_visited. this cannot be a NLSO - // because it may be used before _cinit. - // if we put it in a function, construction still fails on VC7 because - // the atexit table will not have been initialized yet. +// note: allocating memory dynamically would cause trouble if dumping +// the stack from within memory-related code (the allocation hook would +// be reentered, which is not permissible). + +static const size_t maxVisited = 1000; +static const u8* visited[maxVisited]; +static size_t numVisited; -// called by debug_dump_stack but not during shutdown (this must remain valid -// until the very end to allow crash reports) static void ptr_reset_visited() { - delete already_visited_ptrs; - already_visited_ptrs = 0; + numVisited = 0; } static bool ptr_already_visited(const u8* p) { - if(!already_visited_ptrs) - already_visited_ptrs = new PtrSet; + for(size_t i = 0; i < numVisited; i++) + { + if(visited[i] == p) + return true; + } - std::pair ret = already_visited_ptrs->insert(p); - return !ret.second; + if(numVisited < maxVisited) + { + visited[numVisited] = p; + numVisited++; + } + // capacity exceeded + else + { + // warn user - but only once (we can't use the regular + // debug_display_error and wdbg_assert doesn't have a + // suppress mechanism) + static bool haveComplained; + if(!haveComplained) + { + debug_printf("WARNING: ptr_already_visited: capacity exceeded, increase maxVisited\n"); + debug_break(); + haveComplained = true; + } + } + + return false; }