Skip to content

Commit 20480eb

Browse files
Fixed memory leak in Tag.InitializeAsync in case of exceptions (#445)
1 parent c69bbf0 commit 20480eb

File tree

1 file changed

+37
-34
lines changed

1 file changed

+37
-34
lines changed

src/libplctag/Tag.cs

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -708,20 +708,41 @@ public void Initialize()
708708
/// </remarks>
709709
public async Task InitializeAsync(CancellationToken token = default)
710710
{
711-
712711
ThrowIfAlreadyDisposed();
713712
ThrowIfAlreadyInitialized();
714713

714+
SetUpEvents();
715+
716+
var createTask = new TaskCompletionSource<Status>(TaskCreationOptions.RunContinuationsAsynchronously);
717+
createTasks.Push(createTask);
718+
719+
var attributeString = GetAttributeString();
720+
var result = _native.plc_tag_create_ex(attributeString, coreLibCallbackFuncExDelegate, IntPtr.Zero, TIMEOUT_VALUE_THAT_INDICATES_ASYNC_OPERATION);
721+
722+
// Something went wrong locally
723+
if (result < 0)
724+
{
725+
// shouldn't we pop here ?!?
726+
RemoveEvents();
727+
throw new LibPlcTagException((Status)result);
728+
}
729+
else
730+
{
731+
nativeTagHandle = result;
732+
}
733+
715734
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token))
716735
{
717736
cts.CancelAfter(Timeout);
718737

719738
using (cts.Token.Register(() =>
720739
{
721-
if (createTasks.TryPop(out var createTask))
740+
if (createTasks.TryPop(out _))
722741
{
723-
Abort();
724742
RemoveCallback();
743+
Abort();
744+
var destroyResult = (Status)_native.plc_tag_destroy(result);
745+
Debug.Assert(destroyResult == Status.Ok);
725746
RemoveEvents();
726747

727748
if (token.IsCancellationRequested)
@@ -731,43 +752,25 @@ public async Task InitializeAsync(CancellationToken token = default)
731752
}
732753
}))
733754
{
734-
SetUpEvents();
735-
736-
var createTask = new TaskCompletionSource<Status>(TaskCreationOptions.RunContinuationsAsynchronously);
737-
createTasks.Push(createTask);
738-
739-
var attributeString = GetAttributeString();
740-
741-
var result = _native.plc_tag_create_ex(attributeString, coreLibCallbackFuncExDelegate, IntPtr.Zero, TIMEOUT_VALUE_THAT_INDICATES_ASYNC_OPERATION);
742-
743-
// Something went wrong locally
744-
if (result < 0)
745-
{
746-
RemoveEvents();
747-
throw new LibPlcTagException((Status)result);
748-
}
749-
else
750-
{
751-
nativeTagHandle = result;
752-
}
753-
754755
// Await while Pending
755-
if(GetStatus() == Status.Pending)
756+
if (GetStatus() == Status.Pending) // wouldn't it be safer to await anyway to avoid possible race conditions?
756757
{
757758
await createTask.Task.ConfigureAwait(false);
758759
}
759-
760-
// On error, tear down and throw
761-
if(createTask.Task.Result != Status.Ok)
762-
{
763-
RemoveCallback();
764-
RemoveEvents();
765-
throw new LibPlcTagException(createTask.Task.Result);
766-
}
767-
768-
_isInitialized = true;
769760
}
770761
}
762+
763+
// On error, tear down and throw
764+
if (createTask.Task.Result != Status.Ok)
765+
{
766+
RemoveCallback();
767+
var destroyResult = (Status)_native.plc_tag_destroy(nativeTagHandle);
768+
Debug.Assert(destroyResult == Status.Ok);
769+
RemoveEvents();
770+
throw new LibPlcTagException(createTask.Task.Result);
771+
}
772+
773+
_isInitialized = true;
771774
}
772775

773776
/// <summary>

0 commit comments

Comments
 (0)