IGNITE-1921 .Net: Fixed handle leak during ComputeJobHolder serialization.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fff85cb2 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fff85cb2 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fff85cb2 Branch: refs/heads/ignite-1816 Commit: fff85cb22bdffb0f758977156d41e683210ed148 Parents: b96886d Author: Pavel Tupitsyn <ptupit...@gridgain.com> Authored: Tue Nov 17 16:46:22 2015 +0300 Committer: vozerov-gridgain <voze...@gridgain.com> Committed: Tue Nov 17 16:46:22 2015 +0300 ---------------------------------------------------------------------- .../Compute/ComputeApiTest.cs | 22 +++++- .../Impl/Compute/ComputeImpl.cs | 12 ++- .../Impl/Compute/ComputeTaskHolder.cs | 79 +++++++++++++------- 3 files changed, 84 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/fff85cb2/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs index f02e67e..cb582b7 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs @@ -1087,6 +1087,16 @@ namespace Apache.Ignite.Core.Tests.Compute Assert.AreEqual(_grid1.GetCompute().ClusterGroup.GetNodes().Count, res); } + [Test] + public void TestExceptions() + { + Assert.Throws<BinaryObjectException>(() => _grid1.GetCompute().Broadcast(new InvalidComputeAction())); + + Assert.Throws<BinaryObjectException>( + () => _grid1.GetCompute().Execute<NetSimpleJobArgument, NetSimpleJobResult, NetSimpleTaskResult>( + typeof (NetSimpleTask), new NetSimpleJobArgument(-1))); + } + /// <summary> /// Create configuration. /// </summary> @@ -1143,7 +1153,7 @@ namespace Apache.Ignite.Core.Tests.Compute for (int i = 0; i < subgrid.Count; i++) { - NetSimpleJob job = new NetSimpleJob {Arg = arg}; + var job = arg.Arg > 0 ? new NetSimpleJob {Arg = arg} : new InvalidNetSimpleJob(); jobs[job] = subgrid[i]; } @@ -1183,6 +1193,11 @@ namespace Apache.Ignite.Core.Tests.Compute } } + class InvalidNetSimpleJob : NetSimpleJob + { + // No-op. + } + [Serializable] class NetSimpleJobArgument { @@ -1234,6 +1249,11 @@ namespace Apache.Ignite.Core.Tests.Compute } } + class InvalidComputeAction : ComputeAction + { + // No-op. + } + interface IUserInterface<out T> { T Invoke(); http://git-wip-us.apache.org/repos/asf/ignite/blob/fff85cb2/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs index bbb9489..b44b2ee 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs @@ -583,7 +583,17 @@ namespace Apache.Ignite.Core.Impl.Compute var jobHandle = Marshaller.Ignite.HandleRegistry.Allocate(jobHolder); writer.WriteLong(jobHandle); - writer.WriteObject(jobHolder); + + try + { + writer.WriteObject(jobHolder); + } + catch (Exception) + { + Marshaller.Ignite.HandleRegistry.Release(jobHandle); + + throw; + } return jobHandle; } http://git-wip-us.apache.org/repos/asf/ignite/blob/fff85cb2/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs index 8f9d06a..e992245 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs @@ -221,34 +221,8 @@ namespace Apache.Ignite.Core.Impl.Compute else { writer.WriteBoolean(true); // Map produced result. - writer.WriteInt(map.Count); // Amount of mapped jobs. - var jobHandles = new List<long>(map.Count); - - foreach (KeyValuePair<IComputeJob<T>, IClusterNode> mapEntry in map) - { - var job = new ComputeJobHolder(_compute.ClusterGroup.Ignite as Ignite, mapEntry.Key.ToNonGeneric()); - - IClusterNode node = mapEntry.Value; - - var jobHandle = ignite.HandleRegistry.Allocate(job); - - jobHandles.Add(jobHandle); - - writer.WriteLong(jobHandle); - - if (node.IsLocal) - writer.WriteBoolean(false); // Job is not serialized. - else - { - writer.WriteBoolean(true); // Job is serialized. - writer.WriteObject(job); - } - - writer.WriteGuid(node.Id); - } - - _jobHandles = jobHandles; + _jobHandles = WriteJobs(writer, map); } } else @@ -277,6 +251,57 @@ namespace Apache.Ignite.Core.Impl.Compute } } + /// <summary> + /// Writes job map. + /// </summary> + /// <param name="writer">Writer.</param> + /// <param name="map">Map</param> + /// <returns>Job handle list.</returns> + private static List<long> WriteJobs(BinaryWriter writer, IDictionary<IComputeJob<T>, IClusterNode> map) + { + Debug.Assert(writer != null && map != null); + + writer.WriteInt(map.Count); // Amount of mapped jobs. + + var jobHandles = new List<long>(map.Count); + var ignite = writer.Marshaller.Ignite; + + try + { + foreach (KeyValuePair<IComputeJob<T>, IClusterNode> mapEntry in map) + { + var job = new ComputeJobHolder(ignite, mapEntry.Key.ToNonGeneric()); + + IClusterNode node = mapEntry.Value; + + var jobHandle = ignite.HandleRegistry.Allocate(job); + + jobHandles.Add(jobHandle); + + writer.WriteLong(jobHandle); + + if (node.IsLocal) + writer.WriteBoolean(false); // Job is not serialized. + else + { + writer.WriteBoolean(true); // Job is serialized. + writer.WriteObject(job); + } + + writer.WriteGuid(node.Id); + } + } + catch (Exception) + { + foreach (var handle in jobHandles) + ignite.HandleRegistry.Release(handle); + + throw; + } + + return jobHandles; + } + /** <inheritDoc /> */ public int JobResultLocal(ComputeJobHolder job) {