summaryrefslogtreecommitdiffstats
path: root/third_party/tcmalloc/vendor/src/symbolize.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/tcmalloc/vendor/src/symbolize.cc')
-rw-r--r--third_party/tcmalloc/vendor/src/symbolize.cc28
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
}