linshibo / gperftools

Automatically exported from code.google.com/p/gperftools
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Heap Checker considers data belonging to dead threads to be live (Linux) #537

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Heap Checker treats all memory ranges mapped by libpthread as live, with the 
exception of those ranges which contain the stack pointer of a running thread. 
On Linux, libpthread does not immediately unmap the stack on thread death. As a 
result, stacks of dead threads may still exist in memory and will be treated as 
live by Heap Checker.

Reproducer:

#include <pthread.h>                                                            

#include <stdio.h>                                                              

#include <stdlib.h>                                                             

void *thread_func(void *) {
  // Print the stack range for reference.
  pthread_attr_t attr;
  pthread_getattr_np(pthread_self(), &attr);
  void *stackaddr;
  size_t stacksize;
  pthread_attr_getstack(&attr, &stackaddr, &stacksize);
  printf("Stack at %p-%p\n", stackaddr, (char *)stackaddr + stacksize);

  void *leaked = malloc(31337);
  printf("%p\n", leaked); // break optimization                                                                                                                                                              
}                                                                               

int main() {                                                                    

  pthread_t pid;                                                                                                                                                                                             
  pthread_create(&pid, 0, thread_func, 0);                                                                                                                                                                   
  pthread_join(pid, 0);                                                                                                                                                                                      
  return 0;                                                                                                                                                                                                  
}

Build with -pthread and -ltcmalloc, run with HEAPCHECK=strict or 
HEAPCHECK=normal. Heap checker reports no leaks, when in fact we have a leaked 
block of 31337 bytes.

Now run with HEAPCHECK=strict PERFTOOLS_VERBOSE=20.

On stdout:

Stack at 0x7f8792bf8000-0x7f87933f9000
[...]

On stderr:

[...]
Checking for whole-program memory leaks                                         

Disabling allocations from /lib/x86_64-linux-gnu/libpthread-2.15.so at depth 1: 

Global memory regions made by /lib/x86_64-linux-gnu/libpthread-2.15.so will be 
live data                                                                       

Disabling allocations from /lib/x86_64-linux-gnu/ld-2.15.so at depth 2:         

Global memory regions made by /lib/x86_64-linux-gnu/ld-2.15.so will be live 
data                                                                            

Found 0 threads (from pid 32364)                                                

Looking into ./a.out: 0x601000..0x602000                                        

Looking into [heap]: 0x21c3000..0x23dc000                                       

Looking into UNNAMED: 0x7f8792bf9000..0x7f87933f9000 
[...]
Looking for heap pointers in 0x7f8792bf9000 of 8388608 bytes                    

Got pointer into 0x22e0000 at +0 offset                                         

Found pointer to 0x22e0000 of 31337 bytes at 0x7f87933f7780 inside 
0x7f8792bf9000 of size 8388608
[...]

Original issue reported on code.google.com by earth...@google.com on 5 Jun 2013 at 10:36

GoogleCodeExporter commented 9 years ago
any ideas how this can be addressed ?

Original comment by alkondratenko on 6 Jul 2013 at 11:15

GoogleCodeExporter commented 9 years ago
I think you could make it work if you just treated all libpthread-mapped ranges 
as non-live, except for those ranges that contain stack pointers. I don't think 
you'd lose anything important.

In LeakSanitizer, we intercept pthread_* functions so we always know which 
threads are running and where their data is located. But that would be too 
drastic a change for HeapChecker.

Original comment by earth...@google.com on 7 Jul 2013 at 12:30