fix(r2-01): cancellation observed mid-PDU marks the connection dead before propagating (STAB-15a, task 8)

This commit is contained in:
Joseph Doherty
2026-07-13 10:01:20 -04:00
parent dab0029add
commit 33044061c3
3 changed files with 78 additions and 3 deletions
@@ -521,6 +521,17 @@ public sealed class S7Driver
results[i] = new DataValueSnapshot(value, 0u, now, now);
_health = new DriverHealth(DriverState.Healthy, now, null);
}
catch (OperationCanceledException)
{
// Cancellation observed mid-PDU abandons a half-read ISO-on-TCP response on the
// single gated stream — the handle must be reopened, not reused (STAB-15a). Mark
// dead (we hold _gate) and propagate: the caller cancelled, nobody consumes the
// batch. Marking is unconditional on OCE (not routed through the type classifier):
// whether bytes moved is unknowable, and a false positive costs one cheap reopen
// versus permanent desync for a false negative.
_plcDead = true;
throw;
}
catch (NotSupportedException)
{
results[i] = new DataValueSnapshot(null, StatusBadNotSupported, null, now);
@@ -1057,8 +1068,12 @@ public sealed class S7Driver
}
catch (OperationCanceledException)
{
// Let cancellation propagate rather than turning it into
// a status code — the gate is still held so Release() runs in finally.
// Cancellation observed mid-PDU abandons a half-written ISO-on-TCP request on
// the single gated stream — the handle must be reopened, not reused (STAB-15a).
// Mark dead (we hold _gate) and propagate: the caller cancelled, nobody consumes
// the batch, and Release() still runs in finally. Marking is unconditional on
// OCE — a false positive costs one cheap reopen versus permanent desync.
_plcDead = true;
throw;
}
catch (NotSupportedException)