diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 3c0d00c43c..bcfa03ea1a 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -592,6 +592,8 @@ void DNS_Mgr::Resolve() } else --num_pending; + + delete dr; } } @@ -847,6 +849,7 @@ const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr) if ( d->Expired() ) { dns_mgr->addr_mappings.Remove(&h); + delete d; return 0; } @@ -866,6 +869,7 @@ TableVal* DNS_Mgr::LookupNameInCache(string name) { HashKey h(name.c_str()); dns_mgr->host_mappings.Remove(&h); + delete d; return 0; } @@ -1038,14 +1042,29 @@ void DNS_Mgr::CheckAsyncHostRequest(const char* host, bool timeout) } } -void DNS_Mgr::Process() +void DNS_Mgr::Flush() { + DoProcess(false); + IterCookie* cookie = addr_mappings.InitForIteration(); + DNS_Mapping* dm; + + host_mappings.Clear(); + addr_mappings.Clear(); + } + +void DNS_Mgr::Process() + { + DoProcess(false); + } + +void DNS_Mgr::DoProcess(bool flush) + { while ( asyncs_timeouts.size() > 0 ) { AsyncRequest* req = asyncs_timeouts.top(); - if ( req->time + DNS_TIMEOUT > current_time() ) + if ( req->time + DNS_TIMEOUT > current_time() || flush ) break; if ( req->IsAddrReq() ) @@ -1086,6 +1105,8 @@ void DNS_Mgr::Process() CheckAsyncHostRequest(dr->ReqHost(), true); IssueAsyncRequests(); + + delete dr; } } diff --git a/src/DNS_Mgr.h b/src/DNS_Mgr.h index c4abb93525..6f16d9661d 100644 --- a/src/DNS_Mgr.h +++ b/src/DNS_Mgr.h @@ -49,6 +49,7 @@ public: virtual ~DNS_Mgr(); bool Init(); + void Flush(); // Looks up the address or addresses of the given host, and returns // a set of addr. @@ -111,6 +112,9 @@ protected: void CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout); void CheckAsyncHostRequest(const char* host, bool timeout); + // Process outstanding requests. + void DoProcess(bool flush); + // IOSource interface. virtual void GetFds(int* read, int* write, int* except); virtual double NextTimestamp(double* network_time); diff --git a/src/Dict.cc b/src/Dict.cc index c0e2d0e4d2..c71cf4c417 100644 --- a/src/Dict.cc +++ b/src/Dict.cc @@ -67,6 +67,19 @@ Dictionary::Dictionary(dict_order ordering, int initial_size) } Dictionary::~Dictionary() + { + DeInit(); + delete order; + } + +void Dictionary::Clear() + { + DeInit(); + Init(2); + tbl2 = 0; + } + +void Dictionary::DeInit() { for ( int i = 0; i < num_buckets; ++i ) if ( tbl[i] ) @@ -84,7 +97,6 @@ Dictionary::~Dictionary() } delete [] tbl; - delete order; if ( tbl2 == 0 ) return; @@ -103,7 +115,9 @@ Dictionary::~Dictionary() delete chain; } + delete [] tbl2; + tbl2 = 0; } void* Dictionary::Lookup(const void* key, int key_size, hash_t hash) const diff --git a/src/Dict.h b/src/Dict.h index c7b3a21eac..3a2239ef54 100644 --- a/src/Dict.h +++ b/src/Dict.h @@ -118,11 +118,15 @@ public: void MakeRobustCookie(IterCookie* cookie) { cookies.append(cookie); } + // Remove all entries. + void Clear(); + unsigned int MemoryAllocation() const; private: void Init(int size); void Init2(int size); // initialize second table for resizing + void DeInit(); // Internal version of Insert(). void* Insert(DictEntry* entry, int copy_key); diff --git a/src/Val.cc b/src/Val.cc index 2a8df1c3d7..164994b3b8 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1463,6 +1463,7 @@ TableVal* ListVal::ConvertToSet() const loop_over_list(vals, i) t->Assign(vals[i], 0); + Unref(s); return t; } @@ -1582,6 +1583,7 @@ TableVal::TableVal(TableType* t, Attributes* a) : MutableVal(t) void TableVal::Init(TableType* t) { + ::Ref(t); table_type = t; expire_expr = 0; expire_time = 0; @@ -1604,6 +1606,7 @@ TableVal::~TableVal() if ( timer ) timer_mgr->Cancel(timer); + Unref(table_type); delete table_hash; delete AsTable(); delete subnets; diff --git a/src/Val.h b/src/Val.h index 6ba16114db..d851be311b 100644 --- a/src/Val.h +++ b/src/Val.h @@ -869,7 +869,7 @@ protected: DECLARE_SERIAL(TableVal); - const TableType* table_type; + TableType* table_type; CompositeHash* table_hash; Attributes* attrs; double expire_time; diff --git a/src/bro.bif b/src/bro.bif index cfc735b963..8b435686c4 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -2828,13 +2828,15 @@ public: // Overridden from DNS_Mgr:Lookup:Callback. 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(); } virtual void Resolved(TableVal* addrs) { - Ref(addrs); + // No Ref() for addrs. trigger->Cache(call, addrs); trigger->Release(); } @@ -2842,12 +2844,19 @@ public: virtual void Timeout() { if ( lookup_name ) - trigger->Cache(call, new StringVal("<\?\?\?>")); + { + Val* result = new StringVal("<\?\?\?>"); + trigger->Cache(call, result); + Unref(result); + } + else { ListVal* lv = new ListVal(TYPE_ADDR); 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); } diff --git a/src/main.cc b/src/main.cc index 5ec5423ce6..678b21affb 100644 --- a/src/main.cc +++ b/src/main.cc @@ -229,6 +229,8 @@ void done_with_network() dpm->Done(); timer_mgr->Expire(); + dns_mgr->Flush(); + mgr.Drain(); mgr.Drain(); if ( remote_serializer ) diff --git a/testing/btest/core/leaks/dns.bro b/testing/btest/core/leaks/dns.bro new file mode 100644 index 0000000000..1dce9c2c82 --- /dev/null +++ b/testing/btest/core/leaks/dns.bro @@ -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; + } + + } + diff --git a/testing/btest/core/leaks.bro b/testing/btest/core/leaks/test-all.bro similarity index 100% rename from testing/btest/core/leaks.bro rename to testing/btest/core/leaks/test-all.bro