DavidMorre / gperftools

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

Missing ThreadCache::InitModule() call #204

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. For windows, disable WIN32_DO_PATCHING and directly call do_malloc and
do_free.  This is for using tcmalloc as a special purpose allocator instead
of replacing the system allocator.

What is the expected output? What do you see instead?
tcmalloc::CentralFreeList::RemoveRange N is 0 and assert fails

What version of the product are you using? On what operating system?
1.2 and 1.4

Please provide any additional information below.
TCMallocGuard initializer calls ThreadCache::InitTSD() which sets
tsd_inited_ to true.  If that happens before the first allocation
ThreadCache::GetCache() will not call InitModule() which means
Static::InitStaticVars doesn't get called and allocations will assert
or crash.  This was found when using tcmalloc for specific allocations
instead of replacing the default allocator.
Solution:
Add a call to ThreadCache::InitModule() in
TCMallocGuard::TCMallocGuard(), if it has already been called
phinited protects against double initialization.

Original issue reported on code.google.com by da...@fries.net on 6 Jan 2010 at 4:39

Attachments:

GoogleCodeExporter commented 9 years ago
Thanks for tracking down the problem and providing a fix.  There's an alternate 
fix, 
which is to change the line
   free(malloc(1))
in TCMallocGuard to say
   do_free(do_malloc(1))
instead.  Do you mind testing that to see if that also works to fix the 
problems you 
were seeing?  We'll debate here which is better, but get one or the other into 
the 
next release.

Original comment by csilv...@gmail.com on 7 Jan 2010 at 2:22

GoogleCodeExporter commented 9 years ago
Either prevents the crash.  The do_free(do_malloc(1)); method does require 
prototypes
as those functions aren't declared until later in the file.

+++ tcmalloc.cc 2010-01-07 08:29:01.000000000 -0600
@@ -198,6 +198,8 @@ size_t InvalidGetAllocatedSize(void* ptr
   CRASH("Attempt to get the size of an invalid pointer: %p\n", ptr);
   return 0;
 }
+inline void* do_malloc(size_t size);
+inline void do_free(void* ptr);
 }  // unnamed namespace

 // Extract interesting stats

Original comment by da...@fries.net on 7 Jan 2010 at 2:35

GoogleCodeExporter commented 9 years ago
On thinking about this more, I'm wondering why you'r eusing do_malloc/do_free 
instead 
of tc_malloc/tc_free.  Those were the routines that were written with your 
use-case in 
mind: using tcmalloc for some allocations but not others.  Is there any reason 
you 
can't use those?

If so, then the right fix (I think), will be to change TCMallocGuard to call 
tc_free(tc_mnalloc(1)) rather than malloc/free.

Original comment by csilv...@gmail.com on 7 Jan 2010 at 4:45

GoogleCodeExporter commented 9 years ago
I tc_malloc or tc_free weren't available in the 1.2 release we started using.  
They 
are appreciated and will be used in the future as part of upgraded tcmalloc.

Original comment by da...@fries.net on 16 Jan 2010 at 7:26

GoogleCodeExporter commented 9 years ago
OK, makes sense.  My plan is to change TCMallocGuard to call 
tc_free(tc_malloc()) in
the next release, so if/when you upgrade to a new release, you should be able to
replace your calls from do_* to tc_*, and that should fix the problem for you.

Original comment by csilv...@gmail.com on 17 Jan 2010 at 3:56

GoogleCodeExporter commented 9 years ago
This is done in perftools 1.5, just released.

Original comment by csilv...@gmail.com on 20 Jan 2010 at 11:05