1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 45    Callback Data Registry */
10 
11 /*
12  * Use these to find memory leaks
13  */
14 
15 #include "squid.h"
16 
17 #if USE_LEAKFINDER
18 
19 #include "LeakFinder.h"
20 #include "SquidTime.h"
21 #include "Store.h"
22 
23 /* ========================================================================= */
24 
LeakFinderPtr(void * p,const char * f,const int l)25 LeakFinderPtr::LeakFinderPtr(void *p , const char *f, const int l) :
26     file(f),
27     line(l),
28     when(squid_curtime)
29 {
30     // XXX: these bits should be done by hash_link()
31     key = p;
32     next = NULL;
33 }
34 
35 /* ========================================================================= */
36 
LeakFinder()37 LeakFinder::LeakFinder() :
38     count(0),
39     last_dump(0)
40 {
41     debugs(45, 3, "LeakFinder constructed");
42     table = hash_create(cmp, 1 << 8, hash);
43 #if 0
44     /* if this is desired to reinstate, add a
45      * RegisterWithCacheManager method
46      */
47     cachemgrRegister("leaks",
48                      "Memory Leak Tracking",
49                      cachemgr_dump, 0, 1);
50 #endif
51 }
52 
53 void *
addSome(void * p,const char * file,int line)54 LeakFinder::addSome(void *p, const char *file, int line)
55 {
56     assert(hash_lookup(table, p) == NULL);
57     LeakFinderPtr *c = new LeakFinderPtr(p, file, line);
58     hash_join(table, c);
59     ++count;
60     return p;
61 }
62 
63 void *
touch(void * p,const char * file,int line)64 LeakFinder::touch(void *p, const char *file, int line)
65 {
66     assert(p);
67     LeakFinderPtr *c = (LeakFinderPtr *) hash_lookup(table, p);
68     assert(c);
69     c->file = file;
70     c->line = line;
71     c->when = squid_curtime;
72     return p;
73 }
74 
75 void *
freeSome(void * p,const char * file,int line)76 LeakFinder::freeSome(void *p, const char *file, int line)
77 {
78     assert(p);
79     LeakFinderPtr *c = (LeakFinderPtr *) hash_lookup(table, p);
80     assert(c);
81     hash_remove_link(table, c);
82     --count;
83     delete c;
84     dump();
85     return p;
86 }
87 
88 /* ========================================================================= */
89 
90 int
cmp(const void * p1,const void * p2)91 LeakFinder::cmp(const void *p1, const void *p2)
92 {
93     return (char *) p1 - (char *) p2;
94 }
95 
96 unsigned int
hash(const void * p,unsigned int mod)97 LeakFinder::hash(const void *p, unsigned int mod)
98 {
99     return ((unsigned long) p >> 8) % mod;
100 }
101 
102 void
dump()103 LeakFinder::dump()
104 {
105     if (0 == count)
106         return;
107 
108     if (squid_curtime == last_dump)
109         return;
110 
111     last_dump = squid_curtime;
112 
113     debugs(45, DBG_IMPORTANT, "Tracking " << count << " pointers");
114 
115     hash_first(table);
116 
117     LeakFinderPtr *c;
118 
119     while ((c = (LeakFinderPtr *)hash_next(table))) {
120         debugs(45, DBG_IMPORTANT, std::setw(20) << c->key << " last used " << std::setw(9) << (squid_curtime - c->when) <<
121                " seconds ago by " << c->file << ":" << c->line);
122     }
123 }
124 
125 #endif /* USE_LEAKFINDER */
126 
127