File google-perftools-tc_free_thread_res.patch of Package google-perftools
Index: google-perftools-1.5/src/tcmalloc.cc
===================================================================
--- google-perftools-1.5.orig/src/tcmalloc.cc
+++ google-perftools-1.5/src/tcmalloc.cc
@@ -131,8 +131,10 @@
#include "system-alloc.h"
#include "tcmalloc_guard.h"
#include "thread_cache.h"
+#include <netinet/in.h>
+
#if (defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)) && !defined(WIN32_OVERRIDE_ALLOCATORS)
# define WIN32_DO_PATCHING 1
#endif
@@ -938,8 +940,9 @@ static inline ThreadCache* GetCacheIfPre
void* const p = ThreadCache::GetCacheIfPresent();
return reinterpret_cast<ThreadCache*>(p);
}
+//extern "C" void __orig_libc_free(void*);
// This lets you call back to a given function pointer if ptr is invalid.
// It is used primarily by windows code which wants a specialized callback.
inline void do_free_with_callback(void* ptr, void (*invalid_free_fn)(void*)) {
if (ptr == NULL) return;
@@ -950,8 +953,21 @@ inline void do_free_with_callback(void*
if (cl == 0) {
span = Static::pageheap()->GetDescriptor(p);
if (!span) {
+ // It could be that this is a free from a nss resolv action from
+ // a thread. Try this heuristics to detect it.
+ // As this happens on thread exit, we don't care too much about
+ // the mem leak -- we should call the original libc free() here,
+ // the mem leak -- we should call the original libc free() here,
+ // but I don't know how to do that :-(
+ struct sockaddr_in *si = (struct sockaddr_in*) ptr;
+ fprintf(stderr, "tc_free: invalid pointer %p\n", ptr);
+ if (si->sin_family == AF_INET && si->sin_port == htons(53)) {
+ fprintf(stderr, "... nss allocated ... leak it rather than crash!\n");
+ //__libc_free(ptr);
+ return;
+ }
// span can be NULL because the pointer passed in is invalid
// (not something returned by malloc or friends), or because the
// pointer was allocated with some other allocator besides
// tcmalloc. The latter can happen if tcmalloc is linked in via