mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
Merge remote-tracking branch 'origin/topic/jsiwek/ticket946'
Closes #946. * origin/topic/jsiwek/ticket946: Fix memory leaks resulting from 'when' and 'return when' statements. Fix three bugs with 'when' and 'return when' statements. Addresses #946
This commit is contained in:
commit
d931079021
17 changed files with 265 additions and 70 deletions
12
CHANGES
12
CHANGES
|
@ -1,14 +1,22 @@
|
||||||
|
|
||||||
|
2.1-336 | 2013-03-06 15:08:06 -0800
|
||||||
|
|
||||||
|
* Fix memory leaks resulting from 'when' and 'return when'
|
||||||
|
statements. Addresses #946. (Jon Siwek)
|
||||||
|
|
||||||
|
* Fix three bugs with 'when' and 'return when' statements. Addresses
|
||||||
|
#946. (Jon Siwek)
|
||||||
|
|
||||||
2.1-333 | 2013-03-06 14:59:47 -0800
|
2.1-333 | 2013-03-06 14:59:47 -0800
|
||||||
|
|
||||||
* Add parsing for GTPv1 extension headers and control messages. (Jon Siwek)
|
* Add parsing for GTPv1 extension headers and control messages. (Jon Siwek)
|
||||||
|
|
||||||
This includes:
|
This includes:
|
||||||
|
|
||||||
- a new generic gtpv1_message() event generated for any GTP
|
- A new generic gtpv1_message() event generated for any GTP
|
||||||
message type.
|
message type.
|
||||||
|
|
||||||
- specific events for the create/update/delete PDP context
|
- Specific events for the create/update/delete PDP context
|
||||||
request/response messages.
|
request/response messages.
|
||||||
|
|
||||||
Addresses #934.
|
Addresses #934.
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2.1-333
|
2.1-336
|
||||||
|
|
|
@ -763,7 +763,7 @@ int dbg_handle_debug_input()
|
||||||
Frame* curr_frame = g_frame_stack.back();
|
Frame* curr_frame = g_frame_stack.back();
|
||||||
const BroFunc* func = curr_frame->GetFunction();
|
const BroFunc* func = curr_frame->GetFunction();
|
||||||
if ( func )
|
if ( func )
|
||||||
current_module = func->GetID()->ModuleName();
|
current_module = extract_module_name(func->Name());
|
||||||
else
|
else
|
||||||
current_module = GLOBAL_MODULE_NAME;
|
current_module = GLOBAL_MODULE_NAME;
|
||||||
|
|
||||||
|
|
|
@ -4639,12 +4639,16 @@ Val* CallExpr::Eval(Frame* f) const
|
||||||
{
|
{
|
||||||
const ::Func* func = func_val->AsFunc();
|
const ::Func* func = func_val->AsFunc();
|
||||||
calling_expr = this;
|
calling_expr = this;
|
||||||
|
const CallExpr* current_call = f ? f->GetCall() : 0;
|
||||||
|
|
||||||
if ( f )
|
if ( f )
|
||||||
f->SetCall(this);
|
f->SetCall(this);
|
||||||
|
|
||||||
ret = func->Call(v, f); // No try/catch here; we pass exceptions upstream.
|
ret = func->Call(v, f); // No try/catch here; we pass exceptions upstream.
|
||||||
|
|
||||||
if ( f )
|
if ( f )
|
||||||
f->ClearCall();
|
f->SetCall(current_call);
|
||||||
|
|
||||||
// Don't Unref() the arguments, as Func::Call already did that.
|
// Don't Unref() the arguments, as Func::Call already did that.
|
||||||
delete v;
|
delete v;
|
||||||
|
|
||||||
|
|
|
@ -87,8 +87,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
84
src/Func.cc
84
src/Func.cc
|
@ -54,13 +54,13 @@ bool did_builtin_init = false;
|
||||||
|
|
||||||
vector<Func*> Func::unique_ids;
|
vector<Func*> Func::unique_ids;
|
||||||
|
|
||||||
Func::Func() : scope(0), id(0), return_value(0)
|
Func::Func() : scope(0), type(0)
|
||||||
{
|
{
|
||||||
unique_id = unique_ids.size();
|
unique_id = unique_ids.size();
|
||||||
unique_ids.push_back(this);
|
unique_ids.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Func::Func(Kind arg_kind) : scope(0), kind(arg_kind), id(0), return_value(0)
|
Func::Func(Kind arg_kind) : scope(0), kind(arg_kind), type(0)
|
||||||
{
|
{
|
||||||
unique_id = unique_ids.size();
|
unique_id = unique_ids.size();
|
||||||
unique_ids.push_back(this);
|
unique_ids.push_back(this);
|
||||||
|
@ -68,6 +68,7 @@ Func::Func(Kind arg_kind) : scope(0), kind(arg_kind), id(0), return_value(0)
|
||||||
|
|
||||||
Func::~Func()
|
Func::~Func()
|
||||||
{
|
{
|
||||||
|
Unref(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Func::AddBody(Stmt* /* new_body */, id_list* /* new_inits */,
|
void Func::AddBody(Stmt* /* new_body */, id_list* /* new_inits */,
|
||||||
|
@ -129,6 +130,12 @@ bool Func::DoSerialize(SerialInfo* info) const
|
||||||
if ( ! SERIALIZE(char(kind) ) )
|
if ( ! SERIALIZE(char(kind) ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if ( ! type->Serialize(info) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( ! SERIALIZE(Name()) )
|
||||||
|
return false;
|
||||||
|
|
||||||
// We don't serialize scope as only global functions are considered here
|
// We don't serialize scope as only global functions are considered here
|
||||||
// anyway.
|
// anyway.
|
||||||
return true;
|
return true;
|
||||||
|
@ -160,12 +167,25 @@ bool Func::DoUnserialize(UnserialInfo* info)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
kind = (Kind) c;
|
kind = (Kind) c;
|
||||||
|
|
||||||
|
type = BroType::Unserialize(info);
|
||||||
|
if ( ! type )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char* n;
|
||||||
|
if ( ! UNSERIALIZE_STR(&n, 0) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
name = n;
|
||||||
|
delete [] n;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Func::DescribeDebug(ODesc* d, const val_list* args) const
|
void Func::DescribeDebug(ODesc* d, const val_list* args) const
|
||||||
{
|
{
|
||||||
id->Describe(d);
|
d->Add(Name());
|
||||||
|
|
||||||
RecordType* func_args = FType()->Args();
|
RecordType* func_args = FType()->Args();
|
||||||
|
|
||||||
if ( args )
|
if ( args )
|
||||||
|
@ -196,21 +216,6 @@ void Func::DescribeDebug(ODesc* d, const val_list* args) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Func::SetID(ID *arg_id)
|
|
||||||
{
|
|
||||||
id = arg_id;
|
|
||||||
|
|
||||||
return_value =
|
|
||||||
new ID(string(string(id->Name()) + "_returnvalue").c_str(),
|
|
||||||
SCOPE_FUNCTION, false);
|
|
||||||
return_value->SetType(FType()->YieldType()->Ref());
|
|
||||||
}
|
|
||||||
|
|
||||||
ID* Func::GetReturnValueID() const
|
|
||||||
{
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
TraversalCode Func::Traverse(TraversalCallback* cb) const
|
TraversalCode Func::Traverse(TraversalCallback* cb) const
|
||||||
{
|
{
|
||||||
// FIXME: Make a fake scope for builtins?
|
// FIXME: Make a fake scope for builtins?
|
||||||
|
@ -226,12 +231,6 @@ TraversalCode Func::Traverse(TraversalCallback* cb) const
|
||||||
tc = scope->Traverse(cb);
|
tc = scope->Traverse(cb);
|
||||||
HANDLE_TC_STMT_PRE(tc);
|
HANDLE_TC_STMT_PRE(tc);
|
||||||
|
|
||||||
if ( GetReturnValueID() )
|
|
||||||
{
|
|
||||||
tc = GetReturnValueID()->Traverse(cb);
|
|
||||||
HANDLE_TC_STMT_PRE(tc);
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( unsigned int i = 0; i < bodies.size(); ++i )
|
for ( unsigned int i = 0; i < bodies.size(); ++i )
|
||||||
{
|
{
|
||||||
tc = bodies[i].stmts->Traverse(cb);
|
tc = bodies[i].stmts->Traverse(cb);
|
||||||
|
@ -249,7 +248,8 @@ BroFunc::BroFunc(ID* arg_id, Stmt* arg_body, id_list* aggr_inits,
|
||||||
int arg_frame_size, int priority)
|
int arg_frame_size, int priority)
|
||||||
: Func(BRO_FUNC)
|
: Func(BRO_FUNC)
|
||||||
{
|
{
|
||||||
id = arg_id;
|
name = arg_id->Name();
|
||||||
|
type = arg_id->Type()->Ref();
|
||||||
frame_size = arg_frame_size;
|
frame_size = arg_frame_size;
|
||||||
|
|
||||||
if ( arg_body )
|
if ( arg_body )
|
||||||
|
@ -263,7 +263,6 @@ BroFunc::BroFunc(ID* arg_id, Stmt* arg_body, id_list* aggr_inits,
|
||||||
|
|
||||||
BroFunc::~BroFunc()
|
BroFunc::~BroFunc()
|
||||||
{
|
{
|
||||||
Unref(id);
|
|
||||||
for ( unsigned int i = 0; i < bodies.size(); ++i )
|
for ( unsigned int i = 0; i < bodies.size(); ++i )
|
||||||
Unref(bodies[i].stmts);
|
Unref(bodies[i].stmts);
|
||||||
}
|
}
|
||||||
|
@ -378,7 +377,8 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const
|
||||||
(flow != FLOW_RETURN /* we fell off the end */ ||
|
(flow != FLOW_RETURN /* we fell off the end */ ||
|
||||||
! result /* explicit return with no result */) &&
|
! result /* explicit return with no result */) &&
|
||||||
! f->HasDelayed() )
|
! f->HasDelayed() )
|
||||||
reporter->Warning("non-void function returns without a value: %s", id->Name());
|
reporter->Warning("non-void function returns without a value: %s",
|
||||||
|
Name());
|
||||||
|
|
||||||
if ( result && g_trace_state.DoTrace() )
|
if ( result && g_trace_state.DoTrace() )
|
||||||
{
|
{
|
||||||
|
@ -421,8 +421,7 @@ void BroFunc::AddBody(Stmt* new_body, id_list* new_inits, int new_frame_size,
|
||||||
|
|
||||||
void BroFunc::Describe(ODesc* d) const
|
void BroFunc::Describe(ODesc* d) const
|
||||||
{
|
{
|
||||||
if ( id )
|
d->Add(Name());
|
||||||
id->Describe(d);
|
|
||||||
|
|
||||||
d->NL();
|
d->NL();
|
||||||
d->AddCount(frame_size);
|
d->AddCount(frame_size);
|
||||||
|
@ -450,14 +449,14 @@ IMPLEMENT_SERIAL(BroFunc, SER_BRO_FUNC);
|
||||||
bool BroFunc::DoSerialize(SerialInfo* info) const
|
bool BroFunc::DoSerialize(SerialInfo* info) const
|
||||||
{
|
{
|
||||||
DO_SERIALIZE(SER_BRO_FUNC, Func);
|
DO_SERIALIZE(SER_BRO_FUNC, Func);
|
||||||
return id->Serialize(info) && SERIALIZE(frame_size);
|
return SERIALIZE(frame_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BroFunc::DoUnserialize(UnserialInfo* info)
|
bool BroFunc::DoUnserialize(UnserialInfo* info)
|
||||||
{
|
{
|
||||||
DO_UNSERIALIZE(Func);
|
DO_UNSERIALIZE(Func);
|
||||||
id = ID::Unserialize(info);
|
|
||||||
return id && UNSERIALIZE(&frame_size);
|
return UNSERIALIZE(&frame_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
|
BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
|
||||||
|
@ -465,15 +464,16 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
|
||||||
: Func(BUILTIN_FUNC)
|
: Func(BUILTIN_FUNC)
|
||||||
{
|
{
|
||||||
func = arg_func;
|
func = arg_func;
|
||||||
name = copy_string(make_full_var_name(GLOBAL_MODULE_NAME, arg_name).c_str());
|
name = make_full_var_name(GLOBAL_MODULE_NAME, arg_name);
|
||||||
is_pure = arg_is_pure;
|
is_pure = arg_is_pure;
|
||||||
|
|
||||||
id = lookup_ID(name, GLOBAL_MODULE_NAME, false);
|
ID* id = lookup_ID(Name(), GLOBAL_MODULE_NAME, false);
|
||||||
if ( ! id )
|
if ( ! id )
|
||||||
reporter->InternalError("built-in function %s missing", name);
|
reporter->InternalError("built-in function %s missing", Name());
|
||||||
if ( id->HasVal() )
|
if ( id->HasVal() )
|
||||||
reporter->InternalError("built-in function %s multiply defined", name);
|
reporter->InternalError("built-in function %s multiply defined", Name());
|
||||||
|
|
||||||
|
type = id->Type()->Ref();
|
||||||
id->SetVal(new Val(this));
|
id->SetVal(new Val(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,7 +491,7 @@ Val* BuiltinFunc::Call(val_list* args, Frame* parent) const
|
||||||
#ifdef PROFILE_BRO_FUNCTIONS
|
#ifdef PROFILE_BRO_FUNCTIONS
|
||||||
DEBUG_MSG("Function: %s\n", Name());
|
DEBUG_MSG("Function: %s\n", Name());
|
||||||
#endif
|
#endif
|
||||||
SegmentProfiler(segment_logger, name);
|
SegmentProfiler(segment_logger, Name());
|
||||||
|
|
||||||
if ( sample_logger )
|
if ( sample_logger )
|
||||||
sample_logger->FunctionSeen(this);
|
sample_logger->FunctionSeen(this);
|
||||||
|
@ -522,8 +522,7 @@ Val* BuiltinFunc::Call(val_list* args, Frame* parent) const
|
||||||
|
|
||||||
void BuiltinFunc::Describe(ODesc* d) const
|
void BuiltinFunc::Describe(ODesc* d) const
|
||||||
{
|
{
|
||||||
if ( id )
|
d->Add(Name());
|
||||||
id->Describe(d);
|
|
||||||
d->AddCount(is_pure);
|
d->AddCount(is_pure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,16 +531,13 @@ IMPLEMENT_SERIAL(BuiltinFunc, SER_BUILTIN_FUNC);
|
||||||
bool BuiltinFunc::DoSerialize(SerialInfo* info) const
|
bool BuiltinFunc::DoSerialize(SerialInfo* info) const
|
||||||
{
|
{
|
||||||
DO_SERIALIZE(SER_BUILTIN_FUNC, Func);
|
DO_SERIALIZE(SER_BUILTIN_FUNC, Func);
|
||||||
|
return true;
|
||||||
// We ignore the ID. Func::Serialize() will rebind us anyway.
|
|
||||||
return SERIALIZE(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltinFunc::DoUnserialize(UnserialInfo* info)
|
bool BuiltinFunc::DoUnserialize(UnserialInfo* info)
|
||||||
{
|
{
|
||||||
DO_UNSERIALIZE(Func);
|
DO_UNSERIALIZE(Func);
|
||||||
id = 0;
|
return true;
|
||||||
return UNSERIALIZE_STR(&name, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void builtin_error(const char* msg, BroObj* arg)
|
void builtin_error(const char* msg, BroObj* arg)
|
||||||
|
|
17
src/Func.h
17
src/Func.h
|
@ -47,15 +47,11 @@ public:
|
||||||
virtual void SetScope(Scope* newscope) { scope = newscope; }
|
virtual void SetScope(Scope* newscope) { scope = newscope; }
|
||||||
virtual Scope* GetScope() const { return scope; }
|
virtual Scope* GetScope() const { return scope; }
|
||||||
|
|
||||||
virtual FuncType* FType() const
|
virtual FuncType* FType() const { return type->AsFuncType(); }
|
||||||
{
|
|
||||||
return (FuncType*) id->Type()->AsFuncType();
|
|
||||||
}
|
|
||||||
|
|
||||||
Kind GetKind() const { return kind; }
|
Kind GetKind() const { return kind; }
|
||||||
|
|
||||||
const ID* GetID() const { return id; }
|
const char* Name() const { return name.c_str(); }
|
||||||
void SetID(ID *arg_id);
|
|
||||||
|
|
||||||
virtual void Describe(ODesc* d) const = 0;
|
virtual void Describe(ODesc* d) const = 0;
|
||||||
virtual void DescribeDebug(ODesc* d, const val_list* args) const;
|
virtual void DescribeDebug(ODesc* d, const val_list* args) const;
|
||||||
|
@ -64,7 +60,6 @@ public:
|
||||||
bool Serialize(SerialInfo* info) const;
|
bool Serialize(SerialInfo* info) const;
|
||||||
static Func* Unserialize(UnserialInfo* info);
|
static Func* Unserialize(UnserialInfo* info);
|
||||||
|
|
||||||
ID* GetReturnValueID() const;
|
|
||||||
virtual TraversalCode Traverse(TraversalCallback* cb) const;
|
virtual TraversalCode Traverse(TraversalCallback* cb) const;
|
||||||
|
|
||||||
uint32 GetUniqueFuncID() const { return unique_id; }
|
uint32 GetUniqueFuncID() const { return unique_id; }
|
||||||
|
@ -79,8 +74,8 @@ protected:
|
||||||
vector<Body> bodies;
|
vector<Body> bodies;
|
||||||
Scope* scope;
|
Scope* scope;
|
||||||
Kind kind;
|
Kind kind;
|
||||||
ID* id;
|
BroType* type;
|
||||||
ID* return_value;
|
string name;
|
||||||
uint32 unique_id;
|
uint32 unique_id;
|
||||||
static vector<Func*> unique_ids;
|
static vector<Func*> unique_ids;
|
||||||
};
|
};
|
||||||
|
@ -119,18 +114,16 @@ public:
|
||||||
|
|
||||||
int IsPure() const;
|
int IsPure() const;
|
||||||
Val* Call(val_list* args, Frame* parent) const;
|
Val* Call(val_list* args, Frame* parent) const;
|
||||||
const char* Name() const { return name; }
|
|
||||||
built_in_func TheFunc() const { return func; }
|
built_in_func TheFunc() const { return func; }
|
||||||
|
|
||||||
void Describe(ODesc* d) const;
|
void Describe(ODesc* d) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BuiltinFunc() { func = 0; name = 0; is_pure = 0; }
|
BuiltinFunc() { func = 0; is_pure = 0; }
|
||||||
|
|
||||||
DECLARE_SERIAL(BuiltinFunc);
|
DECLARE_SERIAL(BuiltinFunc);
|
||||||
|
|
||||||
built_in_func func;
|
built_in_func func;
|
||||||
const char* name;
|
|
||||||
int is_pure;
|
int is_pure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -338,7 +338,7 @@ SampleLogger::~SampleLogger()
|
||||||
|
|
||||||
void SampleLogger::FunctionSeen(const Func* func)
|
void SampleLogger::FunctionSeen(const Func* func)
|
||||||
{
|
{
|
||||||
load_samples->Assign(new StringVal(func->GetID()->Name()), 0);
|
load_samples->Assign(new StringVal(func->Name()), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SampleLogger::LocationSeen(const Location* loc)
|
void SampleLogger::LocationSeen(const Location* loc)
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -330,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);
|
||||||
|
@ -424,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>"); }
|
||||||
|
|
||||||
|
@ -79,7 +79,6 @@ private:
|
||||||
friend class TriggerTimer;
|
friend class TriggerTimer;
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void DeleteTrigger();
|
|
||||||
void Register(ID* id);
|
void Register(ID* id);
|
||||||
void Register(Val* val);
|
void Register(Val* val);
|
||||||
void UnregisterAll();
|
void UnregisterAll();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -483,7 +483,7 @@ bool Manager::CreateEventStream(RecordVal* fval)
|
||||||
Unref(fields); // ref'd by lookupwithdefault
|
Unref(fields); // ref'd by lookupwithdefault
|
||||||
stream->num_fields = fieldsV.size();
|
stream->num_fields = fieldsV.size();
|
||||||
stream->fields = fields->Ref()->AsRecordType();
|
stream->fields = fields->Ref()->AsRecordType();
|
||||||
stream->event = event_registry->Lookup(event->GetID()->Name());
|
stream->event = event_registry->Lookup(event->Name());
|
||||||
stream->want_record = ( want_record->InternalInt() == 1 );
|
stream->want_record = ( want_record->InternalInt() == 1 );
|
||||||
Unref(want_record); // ref'd by lookupwithdefault
|
Unref(want_record); // ref'd by lookupwithdefault
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ bool Manager::CreateTableStream(RecordVal* fval)
|
||||||
stream->tab = dst->AsTableVal();
|
stream->tab = dst->AsTableVal();
|
||||||
stream->rtype = val ? val->AsRecordType() : 0;
|
stream->rtype = val ? val->AsRecordType() : 0;
|
||||||
stream->itype = idx->AsRecordType();
|
stream->itype = idx->AsRecordType();
|
||||||
stream->event = event ? event_registry->Lookup(event->GetID()->Name()) : 0;
|
stream->event = event ? event_registry->Lookup(event->Name()) : 0;
|
||||||
stream->currDict = new PDict(InputHash);
|
stream->currDict = new PDict(InputHash);
|
||||||
stream->currDict->SetDeleteFunc(input_hash_delete_func);
|
stream->currDict->SetDeleteFunc(input_hash_delete_func);
|
||||||
stream->lastDict = new PDict(InputHash);
|
stream->lastDict = new PDict(InputHash);
|
||||||
|
|
|
@ -365,7 +365,7 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval)
|
||||||
streams[idx]->id = id->Ref()->AsEnumVal();
|
streams[idx]->id = id->Ref()->AsEnumVal();
|
||||||
streams[idx]->enabled = true;
|
streams[idx]->enabled = true;
|
||||||
streams[idx]->name = id->Type()->AsEnumType()->Lookup(idx);
|
streams[idx]->name = id->Type()->AsEnumType()->Lookup(idx);
|
||||||
streams[idx]->event = event ? event_registry->Lookup(event->GetID()->Name()) : 0;
|
streams[idx]->event = event ? event_registry->Lookup(event->Name()) : 0;
|
||||||
streams[idx]->columns = columns->Ref()->AsRecordType();
|
streams[idx]->columns = columns->Ref()->AsRecordType();
|
||||||
|
|
||||||
DBG_LOG(DBG_LOGGING, "Created new logging stream '%s', raising event %s",
|
DBG_LOG(DBG_LOGGING, "Created new logging stream '%s', raising event %s",
|
||||||
|
|
12
testing/btest/Baseline/language.returnwhen/bro..stdout
Normal file
12
testing/btest/Baseline/language.returnwhen/bro..stdout
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
dummy from async_func() from bro_init()
|
||||||
|
async_func() return result in bro_init(), flag in my_set
|
||||||
|
dummy from bro_init() when block
|
||||||
|
hi!
|
||||||
|
dummy from async_func() from do_another()
|
||||||
|
async_func() return result in do_another(), flag in my_set
|
||||||
|
dummy from do_another() when block
|
||||||
|
hi!
|
||||||
|
dummy from async_func() from do_another()
|
||||||
|
async_func() return result in do_another(), timeout
|
||||||
|
dummy from do_another() when block
|
||||||
|
hi!
|
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() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
79
testing/btest/language/returnwhen.bro
Normal file
79
testing/btest/language/returnwhen.bro
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# @TEST-EXEC: btest-bg-run bro bro -b %INPUT
|
||||||
|
# @TEST-EXEC: btest-bg-wait 15
|
||||||
|
# @TEST-EXEC: btest-diff bro/.stdout
|
||||||
|
|
||||||
|
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