mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Fix memory leaks resulting from 'when' and 'return when' statements.
Addresses #946.
This commit is contained in:
parent
7e5115460c
commit
d158c7ffdf
6 changed files with 106 additions and 6 deletions
|
@ -87,6 +87,7 @@ Frame* Frame::Clone()
|
||||||
|
|
||||||
void Frame::SetTrigger(Trigger* arg_trigger)
|
void Frame::SetTrigger(Trigger* arg_trigger)
|
||||||
{
|
{
|
||||||
|
ClearTrigger();
|
||||||
if ( arg_trigger )
|
if ( arg_trigger )
|
||||||
Ref(arg_trigger);
|
Ref(arg_trigger);
|
||||||
trigger = arg_trigger;
|
trigger = arg_trigger;
|
||||||
|
|
|
@ -926,17 +926,22 @@ void NotifierRegistry::Register(ID* id, NotifierRegistry::Notifier* notifier)
|
||||||
DBG_LOG(DBG_NOTIFIERS, "registering ID %s for notifier %s",
|
DBG_LOG(DBG_NOTIFIERS, "registering ID %s for notifier %s",
|
||||||
id->Name(), notifier->Name());
|
id->Name(), notifier->Name());
|
||||||
|
|
||||||
|
Attr* attr = new Attr(ATTR_TRACKED);
|
||||||
|
|
||||||
if ( id->Attrs() )
|
if ( id->Attrs() )
|
||||||
id->Attrs()->AddAttr(new Attr(ATTR_TRACKED));
|
{
|
||||||
|
if ( ! id->Attrs()->FindAttr(ATTR_TRACKED) )
|
||||||
|
id->Attrs()->AddAttr(attr);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
attr_list* a = new attr_list;
|
attr_list* a = new attr_list;
|
||||||
Attr* attr = new Attr(ATTR_TRACKED);
|
|
||||||
a->append(attr);
|
a->append(attr);
|
||||||
id->SetAttrs(new Attributes(a, id->Type(), false));
|
id->SetAttrs(new Attributes(a, id->Type(), false));
|
||||||
Unref(attr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Unref(attr);
|
||||||
|
|
||||||
NotifierMap::iterator i = ids.find(id->Name());
|
NotifierMap::iterator i = ids.find(id->Name());
|
||||||
|
|
||||||
if ( i != ids.end() )
|
if ( i != ids.end() )
|
||||||
|
@ -967,7 +972,9 @@ void NotifierRegistry::Unregister(ID* id, NotifierRegistry::Notifier* notifier)
|
||||||
if ( i == ids.end() )
|
if ( i == ids.end() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Attr* attr = id->Attrs()->FindAttr(ATTR_TRACKED);
|
||||||
id->Attrs()->RemoveAttr(ATTR_TRACKED);
|
id->Attrs()->RemoveAttr(ATTR_TRACKED);
|
||||||
|
Unref(attr);
|
||||||
|
|
||||||
NotifierSet* s = i->second;
|
NotifierSet* s = i->second;
|
||||||
s->erase(notifier);
|
s->erase(notifier);
|
||||||
|
|
|
@ -242,6 +242,7 @@ bool Trigger::Eval()
|
||||||
|
|
||||||
trigger->Cache(frame->GetCall(), v);
|
trigger->Cache(frame->GetCall(), v);
|
||||||
trigger->Release();
|
trigger->Release();
|
||||||
|
frame->ClearTrigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
Unref(v);
|
Unref(v);
|
||||||
|
@ -251,7 +252,6 @@ bool Trigger::Eval()
|
||||||
timer_mgr->Cancel(timer);
|
timer_mgr->Cancel(timer);
|
||||||
|
|
||||||
Disable();
|
Disable();
|
||||||
UnregisterAll();
|
|
||||||
Unref(this);
|
Unref(this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -331,6 +331,7 @@ void Trigger::Timeout()
|
||||||
#endif
|
#endif
|
||||||
trigger->Cache(frame->GetCall(), v);
|
trigger->Cache(frame->GetCall(), v);
|
||||||
trigger->Release();
|
trigger->Release();
|
||||||
|
frame->ClearTrigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
Unref(v);
|
Unref(v);
|
||||||
|
@ -338,7 +339,6 @@ void Trigger::Timeout()
|
||||||
}
|
}
|
||||||
|
|
||||||
Disable();
|
Disable();
|
||||||
UnregisterAll();
|
|
||||||
Unref(this);
|
Unref(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +426,12 @@ Val* Trigger::Lookup(const CallExpr* expr)
|
||||||
return (i != cache.end()) ? i->second : 0;
|
return (i != cache.end()) ? i->second : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Trigger::Disable()
|
||||||
|
{
|
||||||
|
UnregisterAll();
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
const char* Trigger::Name() const
|
const char* Trigger::Name() const
|
||||||
{
|
{
|
||||||
assert(location);
|
assert(location);
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
|
|
||||||
// Disable this trigger completely. Needed because Unref'ing the trigger
|
// Disable this trigger completely. Needed because Unref'ing the trigger
|
||||||
// may not immediately delete it as other references may still exist.
|
// may not immediately delete it as other references may still exist.
|
||||||
void Disable() { disabled = true; }
|
void Disable();
|
||||||
|
|
||||||
virtual void Describe(ODesc* d) const { d->Add("<trigger>"); }
|
virtual void Describe(ODesc* d) const { d->Add("<trigger>"); }
|
||||||
|
|
||||||
|
|
|
@ -696,7 +696,9 @@ string FuncType::FlavorString() const
|
||||||
|
|
||||||
FuncType::~FuncType()
|
FuncType::~FuncType()
|
||||||
{
|
{
|
||||||
|
Unref(args);
|
||||||
Unref(arg_types);
|
Unref(arg_types);
|
||||||
|
Unref(yield);
|
||||||
}
|
}
|
||||||
|
|
||||||
BroType* FuncType::YieldType()
|
BroType* FuncType::YieldType()
|
||||||
|
|
84
testing/btest/core/leaks/returnwhen.bro
Normal file
84
testing/btest/core/leaks/returnwhen.bro
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
# Needs perftools support.
|
||||||
|
#
|
||||||
|
# @TEST-GROUP: leaks
|
||||||
|
#
|
||||||
|
# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks
|
||||||
|
#
|
||||||
|
# @TEST-EXEC: btest-bg-run bro HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m -b %INPUT
|
||||||
|
# @TEST-EXEC: btest-bg-wait 15
|
||||||
|
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
|
||||||
|
global my_set: set[string] = set();
|
||||||
|
global flag: string = "flag";
|
||||||
|
global done: bool = F;
|
||||||
|
|
||||||
|
function dummyfunc(s: string): string
|
||||||
|
{
|
||||||
|
return "dummy " + s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function async_func(s: string): string
|
||||||
|
{
|
||||||
|
print dummyfunc("from async_func() " + s);
|
||||||
|
|
||||||
|
return when ( flag in my_set )
|
||||||
|
{
|
||||||
|
return flag + " in my_set";
|
||||||
|
}
|
||||||
|
timeout 3sec
|
||||||
|
{
|
||||||
|
return "timeout";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event set_flag()
|
||||||
|
{
|
||||||
|
add my_set[flag];
|
||||||
|
}
|
||||||
|
|
||||||
|
event do_another()
|
||||||
|
{
|
||||||
|
delete my_set[flag];
|
||||||
|
|
||||||
|
local local_dummy = dummyfunc;
|
||||||
|
|
||||||
|
local anon = function(s: string): string { return s + "!"; };
|
||||||
|
|
||||||
|
if ( ! done )
|
||||||
|
schedule 1sec { set_flag() };
|
||||||
|
|
||||||
|
when ( local result = async_func("from do_another()") )
|
||||||
|
{
|
||||||
|
print "async_func() return result in do_another()", result;
|
||||||
|
print local_dummy("from do_another() when block");
|
||||||
|
print anon("hi");
|
||||||
|
if ( result == "timeout" )
|
||||||
|
terminate();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
done = T;
|
||||||
|
schedule 10msec { do_another() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
local local_dummy = dummyfunc;
|
||||||
|
|
||||||
|
local anon = function(s: string): string { return s + "!"; };
|
||||||
|
|
||||||
|
schedule 1sec { set_flag() };
|
||||||
|
|
||||||
|
when ( local result = async_func("from bro_init()") )
|
||||||
|
{
|
||||||
|
print "async_func() return result in bro_init()", result;
|
||||||
|
print local_dummy("from bro_init() when block");
|
||||||
|
print anon("hi");
|
||||||
|
if ( result == "timeout" ) terminate();
|
||||||
|
schedule 10msec { do_another() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue