fix(r2-01): classify ISO-on-TCP framing/desync faults as connection-fatal (STAB-15a, task 7)
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
{
|
||||
"id": 7,
|
||||
"subject": "GREEN: broaden IsS7ConnectionFatal to the ISO-on-TCP framing surface (NOT InvalidDataException) + xmldoc (STAB-15a)",
|
||||
"status": "pending",
|
||||
"status": "completed",
|
||||
"blockedBy": [6]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1256,10 +1256,24 @@ public sealed class S7Driver
|
||||
|
||||
/// <summary>
|
||||
/// True when <paramref name="ex"/> (or any inner exception) is a socket-level / connection
|
||||
/// loss that a reopen can repair — a <see cref="System.Net.Sockets.SocketException"/> /
|
||||
/// <see cref="System.IO.IOException"/> / <see cref="ObjectDisposedException"/>, or an S7.Net
|
||||
/// <see cref="PlcException"/> carrying <see cref="ErrorCode.ConnectionError"/>. A
|
||||
/// data-address / type error (S7.Net's <see cref="ErrorCode.ReadData"/> /
|
||||
/// loss OR an ISO-on-TCP framing/desync fault that a reopen can repair — a
|
||||
/// <see cref="System.Net.Sockets.SocketException"/> / <see cref="System.IO.IOException"/> /
|
||||
/// <see cref="ObjectDisposedException"/>; an S7.Net framing violation
|
||||
/// (<see cref="TPKTInvalidException"/> / <see cref="TPDUInvalidException"/> /
|
||||
/// <see cref="WrongNumberOfBytesException"/>); or a <see cref="PlcException"/> carrying
|
||||
/// <see cref="ErrorCode.ConnectionError"/> or <see cref="ErrorCode.WrongNumberReceivedBytes"/>.
|
||||
/// A framing violation means the single serialized stream's position is untrustworthy — a
|
||||
/// half-read PDU left by a timeout/cancellation makes every later response mis-frame, so only
|
||||
/// a reopen recovers (STAB-15a: the Modbus STAB-3 desync mode rebuilt in S7).
|
||||
/// <para>
|
||||
/// Deliberately NOT <see cref="System.IO.InvalidDataException"/>: the driver's own decode
|
||||
/// backstop (<see cref="ReinterpretRawValue"/> / <see cref="DecodeScalarBlock"/>) throws
|
||||
/// it for a declared-type/address-size CONFIG mismatch on a HEALTHY socket — classifying
|
||||
/// it would churn a full reopen on every read of a mis-authored tag. A genuinely desynced
|
||||
/// stream's very next PDU still lands in TPKT/TPDU/WrongNumber territory, which now tears
|
||||
/// down, so a real desync self-heals within one extra failed call.
|
||||
/// </para>
|
||||
/// A data-address / type error (S7.Net's <see cref="ErrorCode.ReadData"/> /
|
||||
/// <see cref="ErrorCode.WriteData"/> for a bad address, PUT/GET-denied, etc.) is deliberately
|
||||
/// NOT treated as fatal — reopening wouldn't help and would churn a healthy connection.
|
||||
/// </summary>
|
||||
@@ -1271,7 +1285,13 @@ public sealed class S7Driver
|
||||
{
|
||||
if (e is System.Net.Sockets.SocketException or System.IO.IOException or ObjectDisposedException)
|
||||
return true;
|
||||
if (e is PlcException { ErrorCode: ErrorCode.ConnectionError })
|
||||
// ISO-on-TCP framing/desync surface (STAB-15a): the stream position is untrustworthy —
|
||||
// a half-read PDU left by a timeout/cancellation makes every later response mis-frame.
|
||||
// NOTE: deliberately NOT System.IO.InvalidDataException — ReinterpretRawValue throws it
|
||||
// for a declared-type/address-size CONFIG mismatch on a healthy socket.
|
||||
if (e is TPKTInvalidException or TPDUInvalidException or WrongNumberOfBytesException)
|
||||
return true;
|
||||
if (e is PlcException { ErrorCode: ErrorCode.ConnectionError or ErrorCode.WrongNumberReceivedBytes })
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user