fix(twincat): dispose bit-RMW locks on shutdown + guard null parent read (review)
This commit is contained in:
@@ -169,6 +169,10 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
|
||||
_devices.Clear();
|
||||
_tagsByName.Clear();
|
||||
_resolver.Clear(); // drop transient equipment-tag parses so a config change re-parses
|
||||
// Dispose + clear the per-parent-word RMW gates so ReinitializeAsync cycles don't orphan
|
||||
// their SemaphoreSlim instances (each leaks a wait handle once contended).
|
||||
foreach (var sem in _bitRmwLocks.Values) sem.Dispose();
|
||||
_bitRmwLocks.Clear();
|
||||
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
|
||||
}
|
||||
|
||||
@@ -319,9 +323,16 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
|
||||
{
|
||||
results[i] = new WriteResult(readStatus);
|
||||
}
|
||||
else if (parentValue is null)
|
||||
{
|
||||
// Good status but no value — treating null as 0 would write a zeroed
|
||||
// word and clear every bit set on the device. Surface a Bad status and
|
||||
// write nothing rather than corrupt the parent word.
|
||||
results[i] = new WriteResult(TwinCATStatusMapper.BadCommunicationError);
|
||||
}
|
||||
else
|
||||
{
|
||||
var word = Convert.ToUInt32(parentValue ?? 0u);
|
||||
var word = Convert.ToUInt32(parentValue);
|
||||
var updated = Convert.ToBoolean(w.Value) ? word | (1u << bit) : word & ~(1u << bit);
|
||||
var writeStatus = await client.WriteValueAsync(
|
||||
parentPath, TwinCATDataType.UDInt, null, updated, cancellationToken).ConfigureAwait(false);
|
||||
@@ -719,6 +730,10 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
|
||||
_devices.Clear();
|
||||
_tagsByName.Clear();
|
||||
_resolver.Clear(); // drop transient equipment-tag parses so a config change re-parses
|
||||
// Dispose + clear the per-parent-word RMW gates (mirrors ShutdownAsync) so the
|
||||
// SemaphoreSlim instances aren't orphaned on disposal.
|
||||
foreach (var sem in _bitRmwLocks.Values) sem.Dispose();
|
||||
_bitRmwLocks.Clear();
|
||||
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user