Skip to content

Commit c211fba

Browse files
ericstjmigueldeicaza
authored andcommitted
Prevent input tensors from being GC'ed before PInvoke occurs (migueldeicaza#335)
We were seeing test failures because GC would occur after tensor handles were copied to IntPtr array but before PInvoke finished. GC would run the finalizer, which freed the native tensors, while TF was still running. Prevent the GC from finalizing these by telling it we're still using the managed object. There may be more instances of this problem with other types. The generic pattern to search for is a manged object with a finalizer that exposes its native state (like TFDisposable), and that native state is used after the last reference to the managed object in the method and no external reference is guaranteed.
1 parent b35fd79 commit c211fba

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

TensorFlowSharp/Tensorflow.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,6 +1879,8 @@ public TFOperationDesc SetAttr (string attrName, TFTensor [] tensor, TFStatus st
18791879
for (int i = 0; i < tensor.Length; i++)
18801880
unmanaged [i] = tensor [i].handle;
18811881
TF_SetAttrTensorList (handle, attrName, unmanaged, unmanaged.Length, cstatus.handle);
1882+
// prevent finalization of managed TFTensors
1883+
GC.KeepAlive(tensor);
18821884
cstatus.CheckMaybeRaise (status);
18831885
return this;
18841886
}
@@ -2933,6 +2935,10 @@ public TFTensor [] Run (TFOutput [] inputs, TFTensor [] inputValues, TFOutput []
29332935
TF_SessionRun (handle, runOptions == null ? null : runOptions.LLBuffer, inputs, ivals, iLen, outputs, ovals, oLen, topers, tLen, runMetadata == null ? null : runMetadata.LLBuffer, cstatus.handle);
29342936
}
29352937
cstatus.CheckMaybeRaise (status);
2938+
2939+
// prevent finalization of managed TFTensors
2940+
GC.KeepAlive(inputValues);
2941+
29362942
var result = new TFTensor [oLen];
29372943
for (int i = 0; i < oLen; i++) {
29382944
result [i] = new TFTensor (ovals [i]);
@@ -3038,6 +3044,9 @@ public TFTensor [] PartialRun (PartialRunToken token, TFOutput [] inputs, TFTens
30383044
}
30393045
cstatus.CheckMaybeRaise (status);
30403046

3047+
// prevent finalization of managed TFTensors
3048+
GC.KeepAlive(inputValues);
3049+
30413050
var result = new TFTensor [oLen];
30423051
for (int i = 0; i < oLen; i++) {
30433052
result [i] = new TFTensor (ovals [i]);

0 commit comments

Comments
 (0)