Skip to content

Commit eae41a5

Browse files
authored
Fix memory leak from undisposed sockets and event handler retention during server restart (#3608)
* Fix memory leak from undisposed sockets and retained event handlers during server restart When an OPC UA server is stopped and restarted in-process, TcpServerChannel instances were never garbage collected because UaSCBinaryChannel.Dispose() did not close the underlying socket. Pending ReceiveAsync operations kept the channels pinned via SocketAsyncEngine, causing a steady heap growth per cycle. Changes: - Close socket in UaSCBinaryChannel.Dispose() to cancel pending async I/O - Unsubscribe CertificateValidator.CertificateUpdate in StandardServer.Dispose() - Unsubscribe ConfigurationWatcher.Changed in StandardServer.Dispose() - Unsubscribe ConnectionStatusChanged from TransportListeners in ServerBase.Dispose() Verified over 786 restart cycles with stable heap. * Remove verbose comment * Remove redundant event unsubscribe before dispose * Remove duplicate CertificateUpdate unsubscribe (already existed in master)
1 parent cff3743 commit eae41a5

File tree

2 files changed

+2
-0
lines changed

2 files changed

+2
-0
lines changed

Stack/Opc.Ua.Core/Stack/Server/ServerBase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ protected virtual void Dispose(bool disposing)
8181
{
8282
for (int ii = 0; ii < TransportListeners.Count; ii++)
8383
{
84+
TransportListeners[ii].ConnectionStatusChanged -= OnConnectionStatusChanged;
8485
Utils.SilentDispose(TransportListeners[ii]);
8586
}
8687

Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ protected virtual void Dispose(bool disposing)
225225
{
226226
if (disposing)
227227
{
228+
Socket?.Close();
228229
DiscardTokens();
229230
Utils.SilentDispose(Socket);
230231

0 commit comments

Comments
 (0)