fix(twincat): probe recycle honors cancellation — no uncancellable gate wait (05/STAB-12 compounded part); B6 complete (TwinCAT suite 189 green)
This commit is contained in:
@@ -689,7 +689,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
|
||||
// this the IsConnected fast-path would keep handing back the dead client forever
|
||||
// (the compounding bug — native pushes would never recover).
|
||||
if (!success)
|
||||
await RecycleClientAsync(state).ConfigureAwait(false);
|
||||
await RecycleClientAsync(state, ct).ConfigureAwait(false);
|
||||
else
|
||||
// 05/STAB-16: on a healthy tick, re-register any notifications whose replay
|
||||
// failed (a transient AddNotification blip) so they recover without a client swap.
|
||||
@@ -700,8 +700,10 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
|
||||
{
|
||||
// Probe threw — the connect-failure path clears the client only when the CONNECT
|
||||
// failed; a throw from ProbeAsync on an already-connected client would leave it in
|
||||
// place, so force a recycle to guarantee the next tick rebuilds + replays.
|
||||
await RecycleClientAsync(state).ConfigureAwait(false);
|
||||
// place, so force a recycle to guarantee the next tick rebuilds + replays. A shutdown
|
||||
// racing this recycle cancels the gate wait (STAB-12) — exit the loop cleanly.
|
||||
try { await RecycleClientAsync(state, ct).ConfigureAwait(false); }
|
||||
catch (OperationCanceledException) when (ct.IsCancellationRequested) { break; }
|
||||
}
|
||||
|
||||
TransitionDeviceState(state, success ? HostState.Running : HostState.Stopped);
|
||||
@@ -981,9 +983,12 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
|
||||
/// liveness, so without this forced recycle a wire-dead-but-port-open client would keep
|
||||
/// being reused and native pushes would never recover.
|
||||
/// </summary>
|
||||
private async Task RecycleClientAsync(DeviceState device)
|
||||
private async Task RecycleClientAsync(DeviceState device, CancellationToken ct)
|
||||
{
|
||||
await device.ConnectGate.WaitAsync(CancellationToken.None).ConfigureAwait(false);
|
||||
// 05/STAB-12 (compounded part): honor the probe token so a connect wedged under the gate
|
||||
// (TwinCAT's blocking SDK Connect — the un-fixed root, carried) can't hang the probe loop
|
||||
// beyond cancellation. Was CancellationToken.None.
|
||||
await device.ConnectGate.WaitAsync(ct).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (device.Client is { } c)
|
||||
|
||||
Reference in New Issue
Block a user