diff --git a/src/script_opt/ZAM/ZBody.cc b/src/script_opt/ZAM/ZBody.cc index 4e1ff4f63d..f4c7aa3fd2 100644 --- a/src/script_opt/ZAM/ZBody.cc +++ b/src/script_opt/ZAM/ZBody.cc @@ -317,18 +317,45 @@ std::shared_ptr ZBody::BuildProfVec() const { return pv; } -// Helper class for managing dynamic frames to ensure that their memory -// is recovered if a ZBody is exited via an exception. -class ZBodyDynamicFrame { +// Helper class for managing ZBody state to ensure that memory is recovered +// if a ZBody is exited via an exception. +class ZBodyStateManager { public: - ZBodyDynamicFrame(int frame_size) { frame = frame_size > 0 ? new ZVal[frame_size] : nullptr; } + // If fixed_frame is nil then creates a dynamic frame. + ZBodyStateManager(ZVal* _fixed_frame, int frame_size, const std::vector& _managed_slots) + : fixed_frame(_fixed_frame), managed_slots(_managed_slots) { + if ( fixed_frame ) + frame = fixed_frame; + else { + frame = new ZVal[frame_size]; + for ( auto s : managed_slots ) + frame[s].ClearManagedVal(); + } + } - ~ZBodyDynamicFrame() { delete[] frame; } + ~ZBodyStateManager() { + if ( fixed_frame ) { + // Recover memory and reset for use in next call. + for ( auto s : managed_slots ) { + ZVal::DeleteManagedType(frame[s]); + frame[s].ClearManagedVal(); + } + } + + else { + // Recover memory, no need to reset. + for ( auto s : managed_slots ) + ZVal::DeleteManagedType(frame[s]); + delete[] frame; + } + } auto Frame() { return frame; } private: + ZVal* fixed_frame; ZVal* frame; + const std::vector& managed_slots; }; ValPtr ZBody::Exec(Frame* f, StmtFlowType& flow) { @@ -366,7 +393,7 @@ ValPtr ZBody::Exec(Frame* f, StmtFlowType& flow) { } #endif - ZBodyDynamicFrame dynamic_frame(fixed_frame ? 0 : frame_size); + ZBodyStateManager state_mgr(fixed_frame, frame_size, managed_slots); std::unique_ptr local_table_iters; std::vector step_iters(num_step_iters); @@ -375,10 +402,7 @@ ValPtr ZBody::Exec(Frame* f, StmtFlowType& flow) { if ( fixed_frame ) frame = fixed_frame; else { - frame = dynamic_frame.Frame(); - // Clear slots for which we do explicit memory management. - for ( auto s : managed_slots ) - frame[s].ClearManagedVal(); + frame = state_mgr.Frame(); if ( ! table_iters.empty() ) { local_table_iters = std::make_unique(table_iters.size()); @@ -433,31 +457,6 @@ ValPtr ZBody::Exec(Frame* f, StmtFlowType& flow) { ++pc; } - auto result = ret_type ? ret_u->ToVal(ret_type) : nullptr; - - if ( fixed_frame ) { - // Make sure we don't have any dangling iterators. - for ( auto& ti : table_iters ) - ti.Clear(); - - // Free slots for which we do explicit memory management, - // preparing them for reuse. - for ( auto& ms : managed_slots ) { - auto& v = frame[ms]; - ZVal::DeleteManagedType(v); - v.ClearManagedVal(); - } - } - else { - // Free those slots for which we do explicit memory management. - // No need to then clear them, as we're about to throw away - // the entire frame. - for ( auto& ms : managed_slots ) { - auto& v = frame[ms]; - ZVal::DeleteManagedType(v); - } - } - #ifdef ENABLE_ZAM_PROFILE if ( profiling_active ) { tot_CPU_time += util::curr_CPU_time() - start_CPU_time; @@ -468,7 +467,7 @@ ValPtr ZBody::Exec(Frame* f, StmtFlowType& flow) { } #endif - return result; + return ret_type ? ret_u->ToVal(ret_type) : nullptr; } void ZBody::ReportExecutionProfile(ProfMap& pm) { diff --git a/testing/btest/Baseline/core.expr-exception/reporter.log b/testing/btest/Baseline/core.expr-exception/reporter.log index a420ea4620..d16031f8ba 100644 --- a/testing/btest/Baseline/core.expr-exception/reporter.log +++ b/testing/btest/Baseline/core.expr-exception/reporter.log @@ -7,13 +7,13 @@ #open XXXX-XX-XX-XX-XX-XX #fields ts level message location #types time enum string string -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 -XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 16 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 +XXXXXXXXXX.XXXXXX Reporter::ERROR field value missing (c$ftp) <...>/expr-exception.zeek, line 10 #close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/core/expr-exception.zeek b/testing/btest/core/expr-exception.zeek index 941fccb476..e1a248e682 100644 --- a/testing/btest/core/expr-exception.zeek +++ b/testing/btest/core/expr-exception.zeek @@ -1,11 +1,5 @@ # Expressions in an event handler that raise interpreter exceptions # shouldn't abort Zeek entirely, but just return from the function body. -# -# Skip this test when using ZAM. It generates a memory leak on CI under ASAN, -# which causes a build failure. -# -# This should be removed when #4052 has been addressed. -# @TEST-REQUIRES: test "${ZEEK_ZAM}" != "1" # @TEST-EXEC: zeek -b -r $TRACES/wikipedia.trace base/protocols/ftp base/protocols/http base/frameworks/reporter %INPUT >output # @TEST-EXEC: TEST_DIFF_CANONIFIER="$SCRIPTS/diff-remove-abspath | $SCRIPTS/diff-remove-timestamps" btest-diff reporter.log