mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Fixing DNS memory leaks.
Some of the changes only clean up at termination to make perftools happt, but there were some "real" leaks as well. This fixes all DNS leaks I could reproducem, including most likely what's reported in #534. Closing #534. I'm also adding a new btest subdir core/leaks with tests requiring perftools support. These don't compare against base lines but abort whenever perftools reports a leak (with stack information to track it down). Right now, these are passing.
This commit is contained in:
parent
8627b87b3e
commit
bd9c937236
10 changed files with 113 additions and 8 deletions
|
@ -592,6 +592,8 @@ void DNS_Mgr::Resolve()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
--num_pending;
|
--num_pending;
|
||||||
|
|
||||||
|
delete dr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,6 +849,7 @@ const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr)
|
||||||
if ( d->Expired() )
|
if ( d->Expired() )
|
||||||
{
|
{
|
||||||
dns_mgr->addr_mappings.Remove(&h);
|
dns_mgr->addr_mappings.Remove(&h);
|
||||||
|
delete d;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,6 +869,7 @@ TableVal* DNS_Mgr::LookupNameInCache(string name)
|
||||||
{
|
{
|
||||||
HashKey h(name.c_str());
|
HashKey h(name.c_str());
|
||||||
dns_mgr->host_mappings.Remove(&h);
|
dns_mgr->host_mappings.Remove(&h);
|
||||||
|
delete d;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1038,14 +1042,29 @@ void DNS_Mgr::CheckAsyncHostRequest(const char* host, bool timeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DNS_Mgr::Flush()
|
||||||
|
{
|
||||||
|
DoProcess(false);
|
||||||
|
|
||||||
|
IterCookie* cookie = addr_mappings.InitForIteration();
|
||||||
|
DNS_Mapping* dm;
|
||||||
|
|
||||||
|
host_mappings.Clear();
|
||||||
|
addr_mappings.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
void DNS_Mgr::Process()
|
void DNS_Mgr::Process()
|
||||||
{
|
{
|
||||||
|
DoProcess(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DNS_Mgr::DoProcess(bool flush)
|
||||||
|
{
|
||||||
while ( asyncs_timeouts.size() > 0 )
|
while ( asyncs_timeouts.size() > 0 )
|
||||||
{
|
{
|
||||||
AsyncRequest* req = asyncs_timeouts.top();
|
AsyncRequest* req = asyncs_timeouts.top();
|
||||||
|
|
||||||
if ( req->time + DNS_TIMEOUT > current_time() )
|
if ( req->time + DNS_TIMEOUT > current_time() || flush )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ( req->IsAddrReq() )
|
if ( req->IsAddrReq() )
|
||||||
|
@ -1086,6 +1105,8 @@ void DNS_Mgr::Process()
|
||||||
CheckAsyncHostRequest(dr->ReqHost(), true);
|
CheckAsyncHostRequest(dr->ReqHost(), true);
|
||||||
|
|
||||||
IssueAsyncRequests();
|
IssueAsyncRequests();
|
||||||
|
|
||||||
|
delete dr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
virtual ~DNS_Mgr();
|
virtual ~DNS_Mgr();
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
|
void Flush();
|
||||||
|
|
||||||
// Looks up the address or addresses of the given host, and returns
|
// Looks up the address or addresses of the given host, and returns
|
||||||
// a set of addr.
|
// a set of addr.
|
||||||
|
@ -111,6 +112,9 @@ protected:
|
||||||
void CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout);
|
void CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout);
|
||||||
void CheckAsyncHostRequest(const char* host, bool timeout);
|
void CheckAsyncHostRequest(const char* host, bool timeout);
|
||||||
|
|
||||||
|
// Process outstanding requests.
|
||||||
|
void DoProcess(bool flush);
|
||||||
|
|
||||||
// IOSource interface.
|
// IOSource interface.
|
||||||
virtual void GetFds(int* read, int* write, int* except);
|
virtual void GetFds(int* read, int* write, int* except);
|
||||||
virtual double NextTimestamp(double* network_time);
|
virtual double NextTimestamp(double* network_time);
|
||||||
|
|
16
src/Dict.cc
16
src/Dict.cc
|
@ -67,6 +67,19 @@ Dictionary::Dictionary(dict_order ordering, int initial_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary::~Dictionary()
|
Dictionary::~Dictionary()
|
||||||
|
{
|
||||||
|
DeInit();
|
||||||
|
delete order;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dictionary::Clear()
|
||||||
|
{
|
||||||
|
DeInit();
|
||||||
|
Init(2);
|
||||||
|
tbl2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dictionary::DeInit()
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < num_buckets; ++i )
|
for ( int i = 0; i < num_buckets; ++i )
|
||||||
if ( tbl[i] )
|
if ( tbl[i] )
|
||||||
|
@ -84,7 +97,6 @@ Dictionary::~Dictionary()
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] tbl;
|
delete [] tbl;
|
||||||
delete order;
|
|
||||||
|
|
||||||
if ( tbl2 == 0 )
|
if ( tbl2 == 0 )
|
||||||
return;
|
return;
|
||||||
|
@ -103,7 +115,9 @@ Dictionary::~Dictionary()
|
||||||
|
|
||||||
delete chain;
|
delete chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] tbl2;
|
delete [] tbl2;
|
||||||
|
tbl2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Dictionary::Lookup(const void* key, int key_size, hash_t hash) const
|
void* Dictionary::Lookup(const void* key, int key_size, hash_t hash) const
|
||||||
|
|
|
@ -118,11 +118,15 @@ public:
|
||||||
void MakeRobustCookie(IterCookie* cookie)
|
void MakeRobustCookie(IterCookie* cookie)
|
||||||
{ cookies.append(cookie); }
|
{ cookies.append(cookie); }
|
||||||
|
|
||||||
|
// Remove all entries.
|
||||||
|
void Clear();
|
||||||
|
|
||||||
unsigned int MemoryAllocation() const;
|
unsigned int MemoryAllocation() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init(int size);
|
void Init(int size);
|
||||||
void Init2(int size); // initialize second table for resizing
|
void Init2(int size); // initialize second table for resizing
|
||||||
|
void DeInit();
|
||||||
|
|
||||||
// Internal version of Insert().
|
// Internal version of Insert().
|
||||||
void* Insert(DictEntry* entry, int copy_key);
|
void* Insert(DictEntry* entry, int copy_key);
|
||||||
|
|
|
@ -1463,6 +1463,7 @@ TableVal* ListVal::ConvertToSet() const
|
||||||
loop_over_list(vals, i)
|
loop_over_list(vals, i)
|
||||||
t->Assign(vals[i], 0);
|
t->Assign(vals[i], 0);
|
||||||
|
|
||||||
|
Unref(s);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1582,6 +1583,7 @@ TableVal::TableVal(TableType* t, Attributes* a) : MutableVal(t)
|
||||||
|
|
||||||
void TableVal::Init(TableType* t)
|
void TableVal::Init(TableType* t)
|
||||||
{
|
{
|
||||||
|
::Ref(t);
|
||||||
table_type = t;
|
table_type = t;
|
||||||
expire_expr = 0;
|
expire_expr = 0;
|
||||||
expire_time = 0;
|
expire_time = 0;
|
||||||
|
@ -1604,6 +1606,7 @@ TableVal::~TableVal()
|
||||||
if ( timer )
|
if ( timer )
|
||||||
timer_mgr->Cancel(timer);
|
timer_mgr->Cancel(timer);
|
||||||
|
|
||||||
|
Unref(table_type);
|
||||||
delete table_hash;
|
delete table_hash;
|
||||||
delete AsTable();
|
delete AsTable();
|
||||||
delete subnets;
|
delete subnets;
|
||||||
|
|
|
@ -869,7 +869,7 @@ protected:
|
||||||
|
|
||||||
DECLARE_SERIAL(TableVal);
|
DECLARE_SERIAL(TableVal);
|
||||||
|
|
||||||
const TableType* table_type;
|
TableType* table_type;
|
||||||
CompositeHash* table_hash;
|
CompositeHash* table_hash;
|
||||||
Attributes* attrs;
|
Attributes* attrs;
|
||||||
double expire_time;
|
double expire_time;
|
||||||
|
|
17
src/bro.bif
17
src/bro.bif
|
@ -2828,13 +2828,15 @@ public:
|
||||||
// Overridden from DNS_Mgr:Lookup:Callback.
|
// Overridden from DNS_Mgr:Lookup:Callback.
|
||||||
virtual void Resolved(const char* name)
|
virtual void Resolved(const char* name)
|
||||||
{
|
{
|
||||||
trigger->Cache(call, new StringVal(name));
|
Val* result = new StringVal(name);
|
||||||
|
trigger->Cache(call, result);
|
||||||
|
Unref(result);
|
||||||
trigger->Release();
|
trigger->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Resolved(TableVal* addrs)
|
virtual void Resolved(TableVal* addrs)
|
||||||
{
|
{
|
||||||
Ref(addrs);
|
// No Ref() for addrs.
|
||||||
trigger->Cache(call, addrs);
|
trigger->Cache(call, addrs);
|
||||||
trigger->Release();
|
trigger->Release();
|
||||||
}
|
}
|
||||||
|
@ -2842,12 +2844,19 @@ public:
|
||||||
virtual void Timeout()
|
virtual void Timeout()
|
||||||
{
|
{
|
||||||
if ( lookup_name )
|
if ( lookup_name )
|
||||||
trigger->Cache(call, new StringVal("<\?\?\?>"));
|
{
|
||||||
|
Val* result = new StringVal("<\?\?\?>");
|
||||||
|
trigger->Cache(call, result);
|
||||||
|
Unref(result);
|
||||||
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ListVal* lv = new ListVal(TYPE_ADDR);
|
ListVal* lv = new ListVal(TYPE_ADDR);
|
||||||
lv->Append(new AddrVal("0.0.0.0"));
|
lv->Append(new AddrVal("0.0.0.0"));
|
||||||
trigger->Cache(call, lv->ConvertToSet());
|
Val* result = lv->ConvertToSet();
|
||||||
|
trigger->Cache(call, result);
|
||||||
|
Unref(result);
|
||||||
Unref(lv);
|
Unref(lv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,6 +229,8 @@ void done_with_network()
|
||||||
|
|
||||||
dpm->Done();
|
dpm->Done();
|
||||||
timer_mgr->Expire();
|
timer_mgr->Expire();
|
||||||
|
dns_mgr->Flush();
|
||||||
|
mgr.Drain();
|
||||||
mgr.Drain();
|
mgr.Drain();
|
||||||
|
|
||||||
if ( remote_serializer )
|
if ( remote_serializer )
|
||||||
|
|
48
testing/btest/core/leaks/dns.bro
Normal file
48
testing/btest/core/leaks/dns.bro
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# Needs perftools support.
|
||||||
|
#
|
||||||
|
# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks
|
||||||
|
#
|
||||||
|
# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m -r $TRACES/wikipedia.trace %INPUT
|
||||||
|
|
||||||
|
# Add the state tracking information variable to the connection record
|
||||||
|
|
||||||
|
event connection_established(c: connection)
|
||||||
|
{
|
||||||
|
when ( local addrs = lookup_hostname("localhost") )
|
||||||
|
{
|
||||||
|
print "1a", c$id$resp_h, addrs;
|
||||||
|
}
|
||||||
|
timeout 100secs
|
||||||
|
{
|
||||||
|
print "1b", c$id$resp_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
when ( local addrs2 = lookup_hostname("qq.ww.ee.rrrrr") )
|
||||||
|
{
|
||||||
|
print "2a", c$id$resp_h, addrs2;
|
||||||
|
}
|
||||||
|
timeout 100secs
|
||||||
|
{
|
||||||
|
print "2b", c$id$resp_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
when ( local a = lookup_addr(c$id$resp_h) )
|
||||||
|
{
|
||||||
|
print "3a", c$id$resp_h, a;
|
||||||
|
}
|
||||||
|
timeout 100secs
|
||||||
|
{
|
||||||
|
print "3b", c$id$resp_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
when ( local a2 = lookup_addr(1.2.3.4) )
|
||||||
|
{
|
||||||
|
print "4a", c$id$resp_h, a2;
|
||||||
|
}
|
||||||
|
timeout 100secs
|
||||||
|
{
|
||||||
|
print "4b", c$id$resp_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue