diff options
Diffstat (limited to 'third_party/tcmalloc/vendor/src/symbolize.cc')
-rw-r--r-- | third_party/tcmalloc/vendor/src/symbolize.cc | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/third_party/tcmalloc/vendor/src/symbolize.cc b/third_party/tcmalloc/vendor/src/symbolize.cc index dfdfb7e..d90c4b8 100644 --- a/third_party/tcmalloc/vendor/src/symbolize.cc +++ b/third_party/tcmalloc/vendor/src/symbolize.cc @@ -57,6 +57,7 @@ #endif #include <string> #include "base/commandlineflags.h" +#include "base/logging.h" #include "base/sysinfo.h" using std::string; @@ -93,6 +94,15 @@ static char* GetProgramInvocationName() { #endif } +// Prints an error message when you can't run Symbolize(). +static void PrintError(const char* reason) { + RAW_LOG(ERROR, + "*** WARNING: Cannot convert addresses to symbols in output below.\n" + "*** Reason: %s\n" + "*** If you cannot fix this, try running pprof directly.\n", + reason); +} + void SymbolTable::Add(const void* addr) { symbolization_table_[addr] = ""; } @@ -107,13 +117,22 @@ const char* SymbolTable::GetSymbol(const void* addr) { // Note that the forking/etc is not thread-safe or re-entrant. That's // ok for the purpose we need -- reporting leaks detected by heap-checker // -- but be careful if you decide to use this routine for other purposes. +// Returns number of symbols read on error. If can't symbolize, returns 0 +// and emits an error message about why. int SymbolTable::Symbolize() { #if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS_WAIT_H) + PrintError("Perftools does not know how to call a sub-process on this O/S"); return 0; #else const char* argv0 = GetProgramInvocationName(); - if (argv0 == NULL) // can't call symbolize if we can't figure out our name + if (argv0 == NULL) { // can't call symbolize if we can't figure out our name + PrintError("Cannot figure out the name of this executable (argv0)"); return 0; + } + if (access(g_pprof_path->c_str(), R_OK) != 0) { + PrintError("Cannot find 'pprof' (is PPROF_PATH set correctly?)"); + return 0; + } // All this work is to do two-way communication. ugh. int *child_in = NULL; // file descriptors @@ -131,6 +150,7 @@ int SymbolTable::Symbolize() { for (int j = 0; j < i; j++) { close(child_fds[j][0]); close(child_fds[j][1]); + PrintError("Cannot create a socket pair"); return 0; } } else { @@ -156,6 +176,7 @@ int SymbolTable::Symbolize() { close(child_in[1]); close(child_out[0]); close(child_out[1]); + PrintError("Unknown error calling fork()"); return 0; } case 0: { // child @@ -178,6 +199,8 @@ int SymbolTable::Symbolize() { close(child_in[0]); // child uses the 0's, parent uses the 1's close(child_out[0]); // child uses the 0's, parent uses the 1's #ifdef HAVE_POLL_H + // Waiting for 1ms seems to give the OS time to notice any errors. + poll(0, 0, 1); // For maximum safety, we check to make sure the execlp // succeeded before trying to write. (Otherwise we'll get a // SIGPIPE.) For systems without poll.h, we'll just skip this @@ -185,6 +208,7 @@ int SymbolTable::Symbolize() { struct pollfd pfd = { child_in[1], POLLOUT, 0 }; if (!poll(&pfd, 1, 0) || !(pfd.revents & POLLOUT) || (pfd.revents & (POLLHUP|POLLERR))) { + PrintError("Cannot run 'pprof' (is PPROF_PATH set correctly?)"); return 0; } #endif @@ -220,6 +244,7 @@ int SymbolTable::Symbolize() { kSymbolBufferSize - total_bytes_read); if (bytes_read < 0) { close(child_out[1]); + PrintError("Cannot read data from pprof"); return 0; } else if (bytes_read == 0) { close(child_out[1]); @@ -249,6 +274,7 @@ int SymbolTable::Symbolize() { return num_symbols; } } + PrintError("Unkown error (should never occur!)"); return 0; // shouldn't be reachable #endif } |