| Index: base/debug/stack_trace_win.cc
|
| diff --git a/base/debug/stack_trace_win.cc b/base/debug/stack_trace_win.cc
|
| index ceccef5a4e9ee51393c84f5ec49f69551fdcee1d..55d55624088d59a0ac82f09da611b4ee48627ede 100644
|
| --- a/base/debug/stack_trace_win.cc
|
| +++ b/base/debug/stack_trace_win.cc
|
| @@ -26,9 +26,6 @@
|
| // exception. Only used in unit tests.
|
| LPTOP_LEVEL_EXCEPTION_FILTER g_previous_filter = NULL;
|
|
|
| -bool g_initialized_symbols = false;
|
| -DWORD g_init_error = ERROR_SUCCESS;
|
| -
|
| // Prints the exception call stack.
|
| // This is the unit tests exception filter.
|
| long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) {
|
| @@ -43,55 +40,6 @@
|
| GetModuleFileName(NULL, system_buffer, MAX_PATH);
|
| system_buffer[MAX_PATH - 1] = L'\0';
|
| return FilePath(system_buffer);
|
| -}
|
| -
|
| -bool InitializeSymbols() {
|
| - if (g_initialized_symbols)
|
| - return g_init_error == ERROR_SUCCESS;
|
| - g_initialized_symbols = true;
|
| - // Defer symbol load until they're needed, use undecorated names, and get line
|
| - // numbers.
|
| - SymSetOptions(SYMOPT_DEFERRED_LOADS |
|
| - SYMOPT_UNDNAME |
|
| - SYMOPT_LOAD_LINES);
|
| - if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
|
| - g_init_error = GetLastError();
|
| - // TODO(awong): Handle error: SymInitialize can fail with
|
| - // ERROR_INVALID_PARAMETER.
|
| - // When it fails, we should not call debugbreak since it kills the current
|
| - // process (prevents future tests from running or kills the browser
|
| - // process).
|
| - DLOG(ERROR) << "SymInitialize failed: " << g_init_error;
|
| - return false;
|
| - }
|
| -
|
| - // When transferring the binaries e.g. between bots, path put
|
| - // into the executable will get off. To still retrieve symbols correctly,
|
| - // add the directory of the executable to symbol search path.
|
| - // All following errors are non-fatal.
|
| - const size_t kSymbolsArraySize = 1024;
|
| - scoped_ptr<wchar_t[]> symbols_path(new wchar_t[kSymbolsArraySize]);
|
| -
|
| - // Note: The below function takes buffer size as number of characters,
|
| - // not number of bytes!
|
| - if (!SymGetSearchPathW(GetCurrentProcess(),
|
| - symbols_path.get(),
|
| - kSymbolsArraySize)) {
|
| - DLOG(WARNING) << "SymGetSearchPath failed: " << g_init_error;
|
| - g_init_error = GetLastError();
|
| - return false;
|
| - }
|
| -
|
| - std::wstring new_path(std::wstring(symbols_path.get()) +
|
| - L";" + GetExePath().DirName().value());
|
| - if (!SymSetSearchPathW(GetCurrentProcess(), new_path.c_str())) {
|
| - g_init_error = GetLastError();
|
| - DLOG(WARNING) << "SymSetSearchPath failed." << g_init_error;
|
| - return false;
|
| - }
|
| -
|
| - g_init_error = ERROR_SUCCESS;
|
| - return true;
|
| }
|
|
|
| // SymbolContext is a threadsafe singleton that wraps the DbgHelp Sym* family
|
| @@ -118,6 +66,11 @@
|
| Singleton<SymbolContext, LeakySingletonTraits<SymbolContext> >::get();
|
| }
|
|
|
| + // Returns the error code of a failed initialization.
|
| + DWORD init_error() const {
|
| + return init_error_;
|
| + }
|
| +
|
| // For the given trace, attempts to resolve the symbols, and output a trace
|
| // to the ostream os. The format for each line of the backtrace is:
|
| //
|
| @@ -179,10 +132,51 @@
|
| private:
|
| friend struct DefaultSingletonTraits<SymbolContext>;
|
|
|
| - SymbolContext() {
|
| - InitializeSymbols();
|
| - }
|
| -
|
| + SymbolContext() : init_error_(ERROR_SUCCESS) {
|
| + // Initializes the symbols for the process.
|
| + // Defer symbol load until they're needed, use undecorated names, and
|
| + // get line numbers.
|
| + SymSetOptions(SYMOPT_DEFERRED_LOADS |
|
| + SYMOPT_UNDNAME |
|
| + SYMOPT_LOAD_LINES);
|
| + if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
|
| + init_error_ = GetLastError();
|
| + // TODO(awong): Handle error: SymInitialize can fail with
|
| + // ERROR_INVALID_PARAMETER.
|
| + // When it fails, we should not call debugbreak since it kills the current
|
| + // process (prevents future tests from running or kills the browser
|
| + // process).
|
| + DLOG(ERROR) << "SymInitialize failed: " << init_error_;
|
| + return;
|
| + }
|
| +
|
| + init_error_ = ERROR_SUCCESS;
|
| +
|
| + // When transferring the binaries e.g. between bots, path put
|
| + // into the executable will get off. To still retrieve symbols correctly,
|
| + // add the directory of the executable to symbol search path.
|
| + // All following errors are non-fatal.
|
| + const size_t kSymbolsArraySize = 1024;
|
| + scoped_ptr<wchar_t[]> symbols_path(new wchar_t[kSymbolsArraySize]);
|
| +
|
| + // Note: The below function takes buffer size as number of characters,
|
| + // not number of bytes!
|
| + if (!SymGetSearchPathW(GetCurrentProcess(),
|
| + symbols_path.get(),
|
| + kSymbolsArraySize)) {
|
| + DLOG(WARNING) << "SymGetSearchPath failed: ";
|
| + return;
|
| + }
|
| +
|
| + std::wstring new_path(std::wstring(symbols_path.get()) +
|
| + L";" + GetExePath().DirName().value());
|
| + if (!SymSetSearchPathW(GetCurrentProcess(), new_path.c_str())) {
|
| + DLOG(WARNING) << "SymSetSearchPath failed.";
|
| + return;
|
| + }
|
| + }
|
| +
|
| + DWORD init_error_;
|
| base::Lock lock_;
|
| DISALLOW_COPY_AND_ASSIGN(SymbolContext);
|
| };
|
| @@ -194,11 +188,7 @@
|
| // signal() handling in process_util_posix.cc.
|
| g_previous_filter = SetUnhandledExceptionFilter(&StackDumpExceptionFilter);
|
| RouteStdioToConsole();
|
| -
|
| - // Need to initialize symbols early in the process or else this fails on
|
| - // swarming (since symbols are in different directory than in the exes) and
|
| - // also release x64.
|
| - return InitializeSymbols();
|
| + return true;
|
| }
|
|
|
| // Disable optimizations for the StackTrace::StackTrace function. It is
|
| @@ -219,12 +209,18 @@
|
| #pragma optimize("", on)
|
| #endif
|
|
|
| -StackTrace::StackTrace(EXCEPTION_POINTERS* exception_pointers) {
|
| - InitTrace(exception_pointers->ContextRecord);
|
| -}
|
| -
|
| -StackTrace::StackTrace(CONTEXT* context) {
|
| - InitTrace(context);
|
| +StackTrace::StackTrace(const EXCEPTION_POINTERS* exception_pointers) {
|
| + // StackWalk64() may modify context record passed to it, so we will
|
| + // use a copy.
|
| + CONTEXT context_record = *exception_pointers->ContextRecord;
|
| + InitTrace(&context_record);
|
| +}
|
| +
|
| +StackTrace::StackTrace(const CONTEXT* context) {
|
| + // StackWalk64() may modify context record passed to it, so we will
|
| + // use a copy.
|
| + CONTEXT context_record = *context;
|
| + InitTrace(&context_record);
|
| }
|
|
|
| void StackTrace::InitTrace(CONTEXT* context_record) {
|
| @@ -270,8 +266,9 @@
|
|
|
| void StackTrace::OutputToStream(std::ostream* os) const {
|
| SymbolContext* context = SymbolContext::GetInstance();
|
| - if (g_init_error != ERROR_SUCCESS) {
|
| - (*os) << "Error initializing symbols (" << g_init_error
|
| + DWORD error = context->init_error();
|
| + if (error != ERROR_SUCCESS) {
|
| + (*os) << "Error initializing symbols (" << error
|
| << "). Dumping unresolved backtrace:\n";
|
| for (size_t i = 0; (i < count_) && os->good(); ++i) {
|
| (*os) << "\t" << trace_[i] << "\n";
|
|
|