Index: tools/android/heap_profiler/heap_dump.c |
diff --git a/tools/android/heap_profiler/heap_dump.c b/tools/android/heap_profiler/heap_dump.c |
index 731833ec13710e3d2df3b27a68dd1192e6d861e1..7fea55fa8808308c567a48bd9deb57a510d49be0 100644 |
--- a/tools/android/heap_profiler/heap_dump.c |
+++ b/tools/android/heap_profiler/heap_dump.c |
@@ -4,8 +4,6 @@ |
// The client dump tool for libheap_profiler. It attaches to a process (given |
// its pid) and dumps all the libheap_profiler tracking information in JSON. |
-// The target process is frozen (SIGSTOP) while dumping, unless the -n opt. |
-// is passed (in which case the caller is responsible for un/freezing). |
// The JSON output looks like this: |
// { |
// "total_allocated": 908748493, # Total bytes allocated and not freed. |
@@ -33,13 +31,13 @@ |
#include <fcntl.h> |
#include <inttypes.h> |
-#include <signal.h> |
#include <stdbool.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <time.h> |
#include <unistd.h> |
+#include <sys/ptrace.h> |
#include <sys/stat.h> |
#include "tools/android/heap_profiler/heap_profiler.h" |
@@ -55,6 +53,7 @@ static int dump_process_heap( |
int mem_fd, |
FILE* fmaps, |
bool dump_also_allocs, |
+ bool pedantic, // Enable pedantic consistency checks on memory counters. |
char* comment) { |
HeapStats stats; |
time_t tm; |
@@ -83,8 +82,15 @@ static int dump_process_heap( |
// The mmap looks promising. Let's check for the magic marker. |
lseek_abs(mem_fd, start); |
- if (read(mem_fd, &stats, sizeof(stats)) < sizeof(stats)) |
- continue; |
+ ssize_t rsize = read(mem_fd, &stats, sizeof(stats)); |
+ |
+ if (rsize == -1) { |
+ perror("read"); |
+ return -1; |
+ } |
+ |
+ if (rsize < sizeof(stats)) |
+ continue; // A false positive. |
pasko
2014/09/10 12:09:18
this could be a short read, please check for EINTR
Primiano Tucci (use gerrit)
2014/09/10 13:17:35
Very hard this will happen (The Android framework
|
if (stats.magic_start == HEAP_PROFILER_MAGIC_MARKER) { |
stats_mmap_found = true; |
@@ -150,14 +156,14 @@ static int dump_process_heap( |
} |
printf("},\n"); |
- if (dbg_counted_allocs != stats.num_allocs) { |
+ if (pedantic && dbg_counted_allocs != stats.num_allocs) { |
fprintf(stderr, |
"ERROR: inconsistent alloc count (%"PRIu32" vs %"PRIu32").\n", |
dbg_counted_allocs, stats.num_allocs); |
return -1; |
} |
- if (dbg_counted_total_alloc_bytes != stats.total_alloc_bytes) { |
+ if (pedantic && dbg_counted_total_alloc_bytes != stats.total_alloc_bytes) { |
fprintf(stderr, "ERROR: inconsistent alloc totals (%zu vs %zu).\n", |
dbg_counted_total_alloc_bytes, stats.total_alloc_bytes); |
return -1; |
@@ -201,7 +207,7 @@ static int dump_process_heap( |
} |
printf("}\n}\n"); |
- if (dbg_counted_total_alloc_bytes != stats.total_alloc_bytes) { |
+ if (pedantic && dbg_counted_total_alloc_bytes != stats.total_alloc_bytes) { |
fprintf(stderr, "ERROR: inconsistent stacks totals (%zu vs %zu).\n", |
dbg_counted_total_alloc_bytes, stats.total_alloc_bytes); |
return -1; |
@@ -211,25 +217,6 @@ static int dump_process_heap( |
return 0; |
} |
-// If the dump is interrupted, resume the target process before exiting. |
-static void exit_handler() { |
- kill(pid, SIGCONT); |
- waitpid(pid, NULL, 0); |
- exit(-1); |
-} |
- |
-static bool freeze_process() { |
- if (kill(pid, SIGSTOP) != 0) { |
- fprintf(stderr, "Could not freeze the target process.\n"); |
- perror("kill"); |
- return false; |
- } |
- |
- signal(SIGPIPE, exit_handler); |
- signal(SIGINT, exit_handler); |
- return true; |
-} |
- |
// Unfortunately lseek takes a *signed* offset, which is unsuitable for large |
// files like /proc/X/mem on 64-bit. |
static void lseek_abs(int fd, size_t off) { |
@@ -287,18 +274,18 @@ static void read_proc_cmdline(char* cmdline, int size) { |
int main(int argc, char** argv) { |
char c; |
int ret = 0; |
- bool should_freeze_process = true; |
bool dump_also_allocs = false; |
+ bool pedantic = true; |
char comment[1024] = { '\0' }; |
- while (((c = getopt(argc, argv, "nxc:")) & 0x80) == 0) { |
+ while (((c = getopt(argc, argv, "xnc:")) & 0x80) == 0) { |
pasko
2014/09/10 12:09:18
Please provide a short human-readable description
Primiano Tucci (use gerrit)
2014/09/10 13:17:35
OK. I'll expand the usage string.
|
switch (c) { |
- case 'n': |
- should_freeze_process = false; |
- break; |
case 'x': |
dump_also_allocs = true; |
break; |
+ case 'n': |
+ pedantic = false; |
+ break; |
case 'c': |
strlcpy(comment, optarg, sizeof(comment)); |
break; |
@@ -312,8 +299,10 @@ int main(int argc, char** argv) { |
pid = atoi(argv[optind]); |
- if (should_freeze_process && !freeze_process()) |
+ if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) { |
pasko
2014/09/10 12:09:18
ptrace interface is tricky and I am not a good eno
Primiano Tucci (use gerrit)
2014/09/10 13:17:35
Very hard to tell. However PTRACE_ATTACH is the wa
|
+ perror("ptrace"); |
return -1; |
+ } |
// Wait for the process to actually freeze. |
waitpid(pid, NULL, 0); |
@@ -327,10 +316,9 @@ int main(int argc, char** argv) { |
ret = -1; |
if (ret == 0) |
- ret = dump_process_heap(mem_fd, fmaps, dump_also_allocs, comment); |
+ ret = dump_process_heap(mem_fd, fmaps, dump_also_allocs, pedantic, comment); |
- if (should_freeze_process) |
- kill(pid, SIGCONT); |
+ ptrace(PTRACE_DETACH, pid, NULL, NULL); |
pasko
2014/09/10 12:09:18
ptrace manual page says:
"""
While being traced, t
pasko
2014/09/10 12:45:53
please disregard this comment, the quote from abov
Primiano Tucci (use gerrit)
2014/09/10 13:17:35
That is for the case of fork + TRACEME. In the cas
|
// Cleanup. |
fflush(stdout); |