summaryrefslogtreecommitdiff
path: root/src/heap-profile-table.cc
diff options
context:
space:
mode:
authorcsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2009-09-11 18:42:32 +0000
committercsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2009-09-11 18:42:32 +0000
commit19dfa9e3733155e57406fbd082273eb53cb2750e (patch)
tree8c000b5035acf1bd01cb7208972e128bbd98e4b2 /src/heap-profile-table.cc
parent2197cc670204c583bba3903b765c77620f349609 (diff)
downloadgperftools-19dfa9e3733155e57406fbd082273eb53cb2750e.tar.gz
Thu Sep 10 13:51:15 2009 Google Inc. <opensource@google.com>
* google-perftools: version 1.4 release * Add debugallocation library, to catch memory leaks, stomping, etc * Add --raw mode to allow for delayed processing of pprof files * Use less memory when reading CPU profiles * New environment variables to control kernel-allocs (sbrk, memfs, etc) * Add MarkThreadBusy(): performance improvement * Remove static thread-cache-size code; all is dynamic now * Add new HiddenPointer class to heap checker * BUGFIX: pvalloc(0) allocates now (found by new debugalloc library) * BUGFIX: valloc test (not implementation) no longer overruns memory * BUGFIX: GetHeapProfile no longer deadlocks * BUGFIX: Support unmapping memory regions before main * BUGFIX: Fix some malloc-stats formatting * BUGFIX: Don't crash as often when freeing libc-allocated memory * BUGFIX: Deal better with incorrect PPROF_PATH when symbolizing * BUGFIX: weaken new/delete/etc in addition to malloc/free/etc * BUGFIX: Fix return value of GetAllocatedSize * PORTING: Fix mmap-#define problem on some 64-bit systems * PORTING: Call ranlib again (some OS X versions need it) * PORTING: Fix a leak when building with LLVM * PORTING: Remove some unneeded bash-ishs from testing scripts * WINDOWS: Support library unloading as well as loading * WINDOWS/BUGFIX: Set page to 'xrw' instead of 'rw' when patching git-svn-id: http://gperftools.googlecode.com/svn/trunk@76 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
Diffstat (limited to 'src/heap-profile-table.cc')
-rw-r--r--src/heap-profile-table.cc99
1 files changed, 4 insertions, 95 deletions
diff --git a/src/heap-profile-table.cc b/src/heap-profile-table.cc
index 08b7479..e71000f 100644
--- a/src/heap-profile-table.cc
+++ b/src/heap-profile-table.cc
@@ -37,12 +37,6 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> // for write()
#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h> // for socketpair() -- needed by Symbolize
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h> // for wait() -- needed by Symbolize
-#endif
#include <fcntl.h> // for open()
#ifdef HAVE_GLOB_H
#include <glob.h>
@@ -53,6 +47,9 @@
#ifdef HAVE_INTTYPES_H
#include <inttypes.h> // for PRIxPTR
#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <errno.h>
#include <stdarg.h>
#include <string>
@@ -63,6 +60,7 @@
#include "base/logging.h"
#include "raw_printer.h"
+#include "symbolize.h"
#include <google/stacktrace.h>
#include <google/malloc_hook.h>
#include "base/commandlineflags.h"
@@ -84,15 +82,6 @@ DEFINE_bool(cleanup_old_heap_profiles,
EnvToBool("HEAP_PROFILE_CLEANUP", true),
"At initialization time, delete old heap profiles.");
-DEFINE_string(heap_profile_table_pprof,
- EnvToString("PPROF_PATH", "pprof"),
- "Path to pprof to call for reporting function names.");
-
-// heap_profile_table_pprof may be referenced after destructors are
-// called (since that's when leak-checking is done), so we make
-// a more-permanent copy that won't ever get destroyed.
-static string* g_pprof_path = new string(FLAGS_heap_profile_table_pprof);
-
//----------------------------------------------------------------------
// header of the dumped heap profile
@@ -521,86 +510,6 @@ void HeapProfileTable::Snapshot::ReportCallback(const void* ptr,
e->bytes += v->bytes;
}
-// It would be much more efficient to call Symbolize on a bunch of pc's
-// at once, rather than calling one at a time, but this way it's simpler
-// to code, and efficiency probably isn't a top concern when reporting
-// found leaks at program-exit time.
-// 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.
-static bool Symbolize(void *pc, char *out, int out_size) {
-#if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS_WAIT_H)
- return false;
-#elif !defined(HAVE_PROGRAM_INVOCATION_NAME)
- return false; // TODO(csilvers): get argv[0] somehow
-#else
- // All this work is to do two-way communication. ugh.
- extern char* program_invocation_name; // gcc provides this
- int child_in[2]; // file descriptors
- int child_out[2]; // for now, we don't worry about child_err
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_in) == -1) {
- return false;
- }
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_out) == -1) {
- close(child_in[0]);
- close(child_in[1]);
- return false;
- }
- switch (fork()) {
- case -1: { // error
- close(child_in[0]);
- close(child_in[1]);
- close(child_out[0]);
- close(child_out[1]);
- return false;
- }
- case 0: { // child
- close(child_in[1]); // child uses the 0's, parent uses the 1's
- close(child_out[1]); // child uses the 0's, parent uses the 1's
- close(0);
- close(1);
- if (dup2(child_in[0], 0) == -1) _exit(1);
- if (dup2(child_out[0], 1) == -1) _exit(2);
- execlp(g_pprof_path->c_str(), g_pprof_path->c_str(),
- "--symbols", program_invocation_name, NULL);
- _exit(3); // if execvp fails, it's bad news for us
- }
- default: { // parent
- 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
- DumpProcSelfMaps(child_in[1]); // what pprof expects on stdin
- char pcstr[64]; // enough for a single address
- snprintf(pcstr, sizeof(pcstr), // pprof expects format to be 0xXXXXXX...
- "0x%" PRIxPTR "\n", reinterpret_cast<uintptr_t>(pc));
- write(child_in[1], pcstr, strlen(pcstr));
- close(child_in[1]); // that's all we need to write
- int total_bytes_read = 0;
- while (1) {
- int bytes_read = read(child_out[1], out + total_bytes_read,
- out_size - total_bytes_read);
- if (bytes_read < 0) {
- close(child_out[1]);
- return false;
- } else if (bytes_read == 0) {
- close(child_out[1]);
- wait(NULL);
- break;
- } else {
- total_bytes_read += bytes_read;
- }
- }
- // We have successfully read the output of pprof into out. Make sure
- // we got the full symbol (we can tell because it ends with a \n).
- if (total_bytes_read == 0 || out[total_bytes_read - 1] != '\n')
- return false;
- out[total_bytes_read - 1] = '\0'; // remove the trailing newline
- return true;
- }
- }
- return false; // shouldn't be reachable
-#endif
-}
-
void HeapProfileTable::Snapshot::ReportLeaks(const char* checker_name,
const char* filename,
bool should_symbolize) {