fix(r2-01): probe failures mark the handle dead under the gate so the next tick reopens (STAB-15b, task 9)
This commit is contained in:
@@ -1596,17 +1596,39 @@ public sealed class S7Driver
|
||||
await _gate.WaitAsync(probeCts.Token).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
// EnsureConnectedAsync doubles as the reconnect backstop: if a read/write
|
||||
// marked the handle dead (or the socket dropped between ticks), the probe
|
||||
// reopens it here so recovery doesn't wait for the next data call.
|
||||
var plc = await EnsureConnectedAsync(probeCts.Token).ConfigureAwait(false);
|
||||
await plc.ReadStatusAsync(probeCts.Token).ConfigureAwait(false);
|
||||
success = true;
|
||||
try
|
||||
{
|
||||
// EnsureConnectedAsync doubles as the reconnect backstop: if a read/write
|
||||
// marked the handle dead (or the socket dropped between ticks), the probe
|
||||
// reopens it here so recovery doesn't wait for the next data call.
|
||||
var plc = await EnsureConnectedAsync(probeCts.Token).ConfigureAwait(false);
|
||||
await plc.ReadStatusAsync(probeCts.Token).ConfigureAwait(false);
|
||||
success = true;
|
||||
}
|
||||
catch (OperationCanceledException) when (ct.IsCancellationRequested)
|
||||
{
|
||||
// Loop teardown — rethrow to the outer filter (after finally releases the gate).
|
||||
throw;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Probe deadline fired mid-PDU: the CPU-status response may still be in
|
||||
// flight, so the handle can't be reused (half-read ⇒ desync). We hold _gate
|
||||
// here, keeping _plcDead gate-guarded (STAB-15b).
|
||||
_plcDead = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// STAB-15b: classify + mark while holding _gate so a wire-dead/desynced
|
||||
// handle whose TcpClient still claims Connected is reopened by the NEXT
|
||||
// tick's EnsureConnectedAsync instead of being re-probed forever.
|
||||
MarkConnectionDeadIfFatal(ex);
|
||||
}
|
||||
}
|
||||
finally { _gate.Release(); }
|
||||
}
|
||||
catch (OperationCanceledException) when (ct.IsCancellationRequested) { return; }
|
||||
catch { /* transport/timeout/exception — treated as Stopped below */ }
|
||||
catch { /* gate-wait timeout / other — treated as Stopped below (gate contention is not a connection fault) */ }
|
||||
|
||||
TransitionTo(success ? HostState.Running : HostState.Stopped);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user