Skip to content

Fixed listener leak for nested request events after script execution - #1566

Open
Kart03 wants to merge 1 commit into
developfrom
claude/env-var-memory-cleanup-797942
Open

Kart03 wants to merge 1 commit into
developfrom
claude/env-var-memory-cleanup-797942

Conversation

@Kart03

@Kart03 Kart03 commented Oct 15, 2026

Copy link
Copy Markdown

Context

Each script execution registers an execution.run_collection_request.<executionId> listener on the sandbox host (lib/runner/extensions/event.command.js:728). It was added in 7.46.0 with pm.execution.runRequest (#1522), and it is registered whether or not the script calls pm.execution.runRequest. The per-execution cleanup in the host.execute callback removes the other ten execution.<event>.<id> listeners, but not this one. So one listener and its closure stay on the host for every script run until the run ends.

In a 44-VU perf run (about 105 rps, about 1.8 scripts per request), a heap snapshot at 900 s showed 173,356 of these listeners in the host's _events. It was the largest single object in the heap: about 330 B of live memory per script run (+41 MB over 11 min). With this line patched in, the VU thread's live heap stayed flat (135.6 → 136.0 MB over 660 s).

Summary of the change

  • Added this.host.removeAllListeners(EXECUTION_RUN_REQUEST_EVENT_BASE + executionId) to the per-execution cleanup, next to the other removals. This is safe because the sandbox dispatches each pm.execution.runRequest call before it dispatches the execution result, and bridge events arrive in order. The matching execution.run_collection_request_response.<id> listener is already removed at the same point.
  • Added test/unit/event-command-listener-cleanup.test.js: it runs two prerequest scripts on a stub host and checks that no listener keyed by either execution id is left on the host.

Breaking changes

None.

Dependencies

None.

Test plan

  • npx mocha test/unit/event-command-listener-cleanup.test.js: fails without the fix (expected [ …(2) ] to deeply equal [], one leaked listener per execution) and passes with it.
  • npm run test-unit: 572 passing, 10 pending.
  • ESLint is clean on both changed files.

Generated with Claude Code

The per-execution cleanup removed every execution.<event>.<id> listener
except execution.run_collection_request.<id>, registered for every script
since 7.46.0. One listener and its closure stayed on the host per script
run until the run ended.

Co-Authored-By: Claude <[email protected]>
@codecov

codecov Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.55%. Comparing base (9c2d10d) to head (43cb15c).

❌ Your project check has failed because the head coverage (34.33%) is below the target coverage (35.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #1566   +/-   ##
========================================
  Coverage    77.54%   77.55%           
========================================
  Files           51       51           
  Lines         4338     4339    +1     
  Branches      1223     1223           
========================================
+ Hits          3364     3365    +1     
  Misses         731      731           
  Partials       243      243           
Flag Coverage Δ
integration 68.72% <100.00%> (+<0.01%) ⬆️
legacy 34.33% <100.00%> (+0.01%) ⬆️
unit 46.87% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Kart03

Kart03 commented Oct 15, 2026

Copy link
Copy Markdown
Author

Measured before/after on a real workload. This was a copy of the PPC Governor collection (AUTO-1062) run through postman performance run --runner local: 44 VUs, fixed load, 20 min, 6 GiB / 4 CPU container, local test server. The only difference between the two runs is this fix, bundled into the perf lib.

Before After
execution.run_collection_request.* listeners in the VU heap at 240 s / 900 s 42,473 / 161,854 18 / 8 (scripts in flight)
VU live data after forced GCs, 300 / 600 / 780 s 161 / 192 / 210 MB 130 / 132 / 124 MB
Worker memory, minutes 4–12 / after the ACS step (avg) 1.96 / 3.13 GB 1.53 / 2.30 GB
Worker peak 4.00 GB 2.87 GB
Requests with failed assertions 220 220
Transport / script errors 0 / 0 0 / 0

Per request name, the counts and the pass/fail of every assertion are identical. The one exception is the last loop, which runs until time is up and so follows throughput.

Reviewer guide covering all the AUTO-1062 changes, with before/after code and results: https://claude.ai/artifact/S7vBMoFxTA9kjzQHhQTXpt

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants