fix(egress): restart dead daemons and cap inbound scan body size (#455)
test / integration-docker (pull_request) Successful in 20s
lint / lint (push) Successful in 1m1s
test / unit (pull_request) Failing after 1m46s
test / integration-firecracker (pull_request) Successful in 3m22s
test / coverage (pull_request) Has been skipped
test / publish-infra (pull_request) Has been skipped
tracker-policy-pr / check-pr (pull_request) Failing after 10m4s
test / integration-docker (pull_request) Successful in 20s
lint / lint (push) Successful in 1m1s
test / unit (pull_request) Failing after 1m46s
test / integration-firecracker (pull_request) Successful in 3m22s
test / coverage (pull_request) Has been skipped
test / publish-infra (pull_request) Has been skipped
tracker-policy-pr / check-pr (pull_request) Failing after 10m4s
Two complementary fixes for the egress gateway OOM: 1. gateway_init: auto-restart any daemon that dies unexpectedly. The supervisor already had restart_daemon()/request_restart() logic; this wires it into tick() so an OOM-killed mitmdump is respawned without operator intervention. Implements the "eventual" failure policy described in the original module docstring. 2. egress_addon: cap response body bytes passed to the DLP inbound scan at EGRESS_INBOUND_SCAN_LIMIT_BYTES (default 1 MiB). mitmproxy buffers the full response before the hook fires; capping at scan time limits the additional amplification from decoded text and regex strings. Bodies over the limit emit an egress_scan_truncated log event. Set to 0 to disable the cap. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -175,30 +175,30 @@ class TestSupervisor(unittest.TestCase):
|
||||
rc = self._drive(sup)
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_child_crash_does_not_initiate_shutdown(self):
|
||||
# Failure policy (PRD 0024, interim): a child dying
|
||||
# unexpectedly is logged but the supervisor does NOT tear
|
||||
# down the survivors. Verified by giving the crasher
|
||||
# ~0.3s to die, then asserting the long-runner is still
|
||||
# up and the supervisor never set shutdown_at.
|
||||
def test_child_crash_triggers_restart_not_shutdown(self):
|
||||
# Failure policy: a child dying unexpectedly is restarted by the
|
||||
# supervisor rather than leaving egress dead. Verified by waiting for
|
||||
# the original pid to die, then confirming the supervisor spawned a
|
||||
# replacement with a different pid, and that shutdown was never requested.
|
||||
specs = [
|
||||
_DaemonSpec("crasher", ("/bin/sh", "-c", "exit 1")),
|
||||
_DaemonSpec("longrun", (SLEEP, "30")),
|
||||
]
|
||||
sup = _Supervisor(specs)
|
||||
sup.start_all()
|
||||
# Drive ticks for a while; crasher should die, longrun
|
||||
# should survive.
|
||||
deadline = time.monotonic() + 1.0
|
||||
original_pid = sup.procs[0][1].pid
|
||||
|
||||
# Drive ticks until the restart fires (crasher dies → restart queued →
|
||||
# next tick drains the queue and spawns a replacement).
|
||||
deadline = time.monotonic() + 3.0
|
||||
while time.monotonic() < deadline:
|
||||
done = sup.tick()
|
||||
self.assertFalse(done, "loop converged with a child still alive")
|
||||
if sup.procs[0][1].poll() is not None:
|
||||
sup.tick()
|
||||
if sup.procs[0][1].pid != original_pid:
|
||||
break
|
||||
time.sleep(0.05)
|
||||
|
||||
self.assertEqual(1, sup.procs[0][1].returncode,
|
||||
"crasher should have exited 1")
|
||||
self.assertNotEqual(original_pid, sup.procs[0][1].pid,
|
||||
"crasher should have been restarted with a new pid")
|
||||
self.assertIsNone(sup.procs[1][1].poll(),
|
||||
"longrun should still be running")
|
||||
self.assertIsNone(sup.shutdown_at,
|
||||
|
||||
Reference in New Issue
Block a user