docs(archreview): R2-01 S7 fault-path hardening complete — STAB-14/15 fixed, STAB-8 seam documented (task 12)
v2-ci / build (pull_request) Successful in 3m28s
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (pull_request) Failing after 3m34s
v2-ci / unit-tests (pull_request) Failing after 9m12s
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (pull_request) Failing after 1m46s
v2-ci / build (pull_request) Successful in 3m28s
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (pull_request) Failing after 3m34s
v2-ci / unit-tests (pull_request) Failing after 9m12s
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (pull_request) Failing after 1m46s
This commit is contained in:
@@ -167,6 +167,13 @@ are the new STAB-14..17 below.
|
|||||||
|
|
||||||
### 1. Stability
|
### 1. Stability
|
||||||
|
|
||||||
|
> **REMEDIATED by R2-01 (branch `r2/01-s7-fault-hardening`).** Connect-timeout now surfaces as a
|
||||||
|
> `TimeoutException` at the `EnsureConnectedAsync`/`InitializeAsync` source (not an escaping OCE), plus
|
||||||
|
> `when (token.IsCancellationRequested)` filters on the read/write ensure-wrappers (`:488`/`:1000`) and all
|
||||||
|
> three poll-loop OCE catches — so a non-teardown OCE degrades/backs-off instead of killing the loop. Unit
|
||||||
|
> guards T1–T4 (`S7DriverReconnectTests`, incl. the poll-loop-survival regression). Live gate
|
||||||
|
> `S7_1500ConnectTimeoutOutageTests` (env-gated SYN-blackhole, `deferred-live`).
|
||||||
|
|
||||||
**STAB-14 — High — NEW — S7's reconnect wrapper rethrows connect-timeout
|
**STAB-14 — High — NEW — S7's reconnect wrapper rethrows connect-timeout
|
||||||
cancellation, and the poll loop's bare OCE catch then permanently kills the
|
cancellation, and the poll loop's bare OCE catch then permanently kills the
|
||||||
subscription.** `EnsureConnectedAsync` bounds the reopen with a linked
|
subscription.** `EnsureConnectedAsync` bounds the reopen with a linked
|
||||||
@@ -192,6 +199,14 @@ degrade-to-`BadCommunicationError` path), and filter the poll loop's OCE
|
|||||||
catches on `ct.IsCancellationRequested`; add a fake-factory unit test where
|
catches on `ct.IsCancellationRequested`; add a fake-factory unit test where
|
||||||
`OpenAsync` honours a token that only the `CancelAfter` fires.
|
`OpenAsync` honours a token that only the `CancelAfter` fires.
|
||||||
|
|
||||||
|
> **REMEDIATED by R2-01 (branch `r2/01-s7-fault-hardening`).** `IsS7ConnectionFatal` broadened to the
|
||||||
|
> ISO-on-TCP framing surface (`TPKTInvalidException`/`TPDUInvalidException`/`WrongNumberOfBytesException` +
|
||||||
|
> `PlcException{WrongNumberReceivedBytes}`; deliberately NOT `InvalidDataException` — that is the driver's own
|
||||||
|
> config-mismatch decode backstop on a healthy socket). Cancellation observed mid-PDU on read + write now
|
||||||
|
> marks `_plcDead` before propagating; the probe restructured to classify + mark dead under `_gate` so the next
|
||||||
|
> tick reopens a lying/hung handle. Unit guards T5–T9 (`S7DriverReconnectTests`) + negative control
|
||||||
|
> `Read_does_not_reopen_on_a_data_address_error`.
|
||||||
|
|
||||||
**STAB-15 — High — NEW — S7's connection-fatal classification misses
|
**STAB-15 — High — NEW — S7's connection-fatal classification misses
|
||||||
framing/desync errors and cancellation-during-I/O, reproducing Modbus's
|
framing/desync errors and cancellation-during-I/O, reproducing Modbus's
|
||||||
STAB-3 desync; and the probe never marks the handle dead.**
|
STAB-3 desync; and the probe never marks the handle dead.**
|
||||||
@@ -340,6 +355,12 @@ S7's `ComputeBackoffDelay`, `S7Driver.cs:1447`) and a small connect-attempt
|
|||||||
throttle to the lazy-reconnect drivers (S7's `EnsureConnectedAsync` is now
|
throttle to the lazy-reconnect drivers (S7's `EnsureConnectedAsync` is now
|
||||||
the natural home for a last-attempt timestamp).
|
the natural home for a last-attempt timestamp).
|
||||||
|
|
||||||
|
> **SEAM DOCUMENTED by R2-01 (branch `r2/01-s7-fault-hardening`).** The S7 connect-throttle is left to
|
||||||
|
> R2-09 (fleet-wide reconnect-backoff), not implemented driver-locally. `EnsureConnectedAsync`'s `<remarks>`
|
||||||
|
> now names itself as the single gate-serialized choke-point where a last-failed-attempt timestamp plugs in.
|
||||||
|
> (Note: R2-01's STAB-14/15 fixes already *reduce* dead-PLC cost — poll ticks that used to die now back off to
|
||||||
|
> `PollBackoffCap`, and connect-timeouts no longer escape as anomalous OCEs.)
|
||||||
|
|
||||||
**STAB-9 — Medium — `PollGroupEngine`'s `onError` sink is dead code: no
|
**STAB-9 — Medium — `PollGroupEngine`'s `onError` sink is dead code: no
|
||||||
driver passes it.** All five consumers construct the engine without the
|
driver passes it.** All five consumers construct the engine without the
|
||||||
error callback (`ModbusDriver.cs:115`, `AbCipDriver.cs:133`,
|
error callback (`ModbusDriver.cs:115`, `AbCipDriver.cs:133`,
|
||||||
|
|||||||
@@ -77,9 +77,10 @@
|
|||||||
{
|
{
|
||||||
"id": 12,
|
"id": 12,
|
||||||
"subject": "Close-out: whole-suite sweep + update archreview STATUS.md and 05 prior-finding table (STAB-14/15 FIXED, STAB-8 seam noted)",
|
"subject": "Close-out: whole-suite sweep + update archreview STATUS.md and 05 prior-finding table (STAB-14/15 FIXED, STAB-8 seam noted)",
|
||||||
"status": "pending",
|
"status": "completed",
|
||||||
|
"note": "S7 unit 246/246 green; S7 CLI 48/49 (1 pre-existing unrelated comment-scan failure, see deviations); solution BUILD clean (0 errors). Whole-solution dotnet test NOT run per controller memory-constraint (integration suites deferred to serial heavy pass).",
|
||||||
"blockedBy": [5, 7, 8, 9, 10, 11]
|
"blockedBy": [5, 7, 8, 9, 10, 11]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lastUpdated": "2026-07-12"
|
"lastUpdated": "2026-07-13"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,3 +150,21 @@ surface), 03/S2/S3 block-bridging, 03/P1 surgical adds (guard prerequisite in pl
|
|||||||
per-plan task counts, effort, and suggested execution order: [`00-INDEX.md`](00-INDEX.md) §"Round 2
|
per-plan task counts, effort, and suggested execution order: [`00-INDEX.md`](00-INDEX.md) §"Round 2
|
||||||
plans". 193 bite-sized TDD tasks total, ~18–24 dev-days end-to-end; R2-01/02/03 (the re-review's
|
plans". 193 bite-sized TDD tasks total, ~18–24 dev-days end-to-end; R2-01/02/03 (the re-review's
|
||||||
new-and-sharp items) are ~2 days combined.
|
new-and-sharp items) are ~2 days combined.
|
||||||
|
|
||||||
|
**Round-2 execution progress:**
|
||||||
|
|
||||||
|
- **R2-01 (05/STAB-14 + 05/STAB-15) — DONE.** S7 fault-path hardening implemented via 13 TDD tasks
|
||||||
|
on branch `r2/01-s7-fault-hardening` (all in `src/Drivers/.../S7Driver.cs` + `S7DriverReconnectTests.cs`).
|
||||||
|
STAB-14: connect-timeout now surfaces as `TimeoutException` (not an escaping OCE) at the
|
||||||
|
`EnsureConnectedAsync`/`InitializeAsync` source, plus `when (token.IsCancellationRequested)` filters on
|
||||||
|
the read/write ensure-wrappers + all three poll-loop OCE catches — subscription poll loops survive an
|
||||||
|
unreachable-host outage and recover. STAB-15: `IsS7ConnectionFatal` broadened to the ISO-on-TCP framing
|
||||||
|
surface (`TPKTInvalidException`/`TPDUInvalidException`/`WrongNumberOfBytesException` +
|
||||||
|
`PlcException{WrongNumberReceivedBytes}`; deliberately NOT `InvalidDataException`); cancellation observed
|
||||||
|
mid-PDU on read/write marks the handle dead before propagating; the probe restructured to classify + mark
|
||||||
|
dead under the gate so the next tick reopens. STAB-8 (S7 part): documented `EnsureConnectedAsync` as the
|
||||||
|
R2-09 connect-throttle seam (note-only, no throttle here). S7 unit suite 246/246 green (T1–T9 + pinning +
|
||||||
|
negative controls). **Live gate (task 11) `deferred-live`:** `S7_1500ConnectTimeoutOutageTests` authored +
|
||||||
|
skips cleanly offline; run it with env vars `S7_TIMEOUT_OUTAGE_START_CMD` / `S7_TIMEOUT_OUTAGE_STOP_CMD`
|
||||||
|
(SYN-blackhole start/stop, e.g. `docker pause`/`unpause` or `iptables … -j DROP`) on the 10.100.0.35
|
||||||
|
s7_1500 fixture — the connect-*timeout* class the `docker restart` bounce test structurally cannot produce.
|
||||||
|
|||||||
Reference in New Issue
Block a user