[ nant-Bugs-3451075 ] ThreadSafety issues i.e. in TaskBuilderCollection.get_Item

SourceForge.net <[email protected]> Sun, 04 Dec 2011 23:09:37 -0800
Newsgroups gmane.comp.windows.dotnet.nant.devel
Message-ID <[email protected]>
Bugs item #3451075, was opened at 2011-12-04 23:09
Message generated for change (Tracker Item Submitted) made by 
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=402868&aid=3451075&group_id=31650

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Core
Group: None
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: LOBOMINATOR ()
Assigned to: Nobody/Anonymous (nobody)
Summary: ThreadSafety issues i.e. in TaskBuilderCollection.get_Item

Initial Comment:
When I execute the custom made execution task which can execute multiple targets in parallel this works fine locally. On teamcity the taskpatcher tries to patch tasks which is not thread safe. This produces a collection modifed exception. See below

Exception on parallel worker: Collection was modified; enumeration operation may not execute. at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext() at NAnt.Core.TaskBuilderCollection.get_Item(String taskName) at JetBrains.BuildServer.NAntLoggers.TasksPatcher.PatchTask(String name, Type t) in c:\Agent\work\c283f2bd6aafd2d9\src\NAntLoggers\src\TasksPatcher.cs:line 52 at JetBrains.BuildServer.NAntLoggers.TasksPatcher.PatchTasks() in c:\Agent\work\c283f2bd6aafd2d9\src\NAntLoggers\src\TasksPatcher.cs:line 31 at JetBrains.BuildServer.NAntLoggers.NAntListenerImpl.TargetStarted(BuildEventArgs e) in c:\Agent\work\c283f2bd6aafd2d9\src\NAntLoggers\src\NAntListenerImpl.cs:line 82 at JetBrains.BuildServer.NAntLoggers.NAntListener2.TargetStarted(Object sender, BuildEventArgs e) in c:\Agen
 t\work\c283f2bd6aafd2d9\src\NAntLoggers\src\NAntListener2.cs:line 62 at JetBrains.BuildServer.NAntLoggers.NAntListener.TargetStarted(Object sender, BuildEventArgs e) in c:\Agent\work\c283f2bd6aafd2d9\src\NAntLoggers\src\NAntListener.cs:line 33 at NAnt.Core.BuildEventHandler.Invoke(Object sender, BuildEventArgs e) at NAnt.Core.Project.OnTargetStarted(Object sender, BuildEventArgs e) at NAnt.Core.Target.Execute() at NAnt.Core.Project.Execute(String targetName, Boolean forceDependencies) at NAnt.Core.Tasks.CallTask.ExecuteTask() at NAnt.Core.Task.Execute() at bbv.NantTasks.AsyncCallTask.Worker(ConcurrentQueue`1 exceptions, ParallelLoopState state, CallTask task)

Here the task definition

code
[TaskName("asynccall")]
public class AsyncCallTask : Task
{
private readonly ConcurrentBag<CallTask> tasksToBeExecuted;

public AsyncCallTask()
{
this.FailFast = true;
this.MaxDegreeOfParallelism = -1;

this.tasksToBeExecuted = new ConcurrentBag<CallTask>();
}

protected override void ExecuteTask()
{
var exceptions = new ConcurrentQueue<Exception>();
var result = Parallel.ForEach(this.tasksToBeExecuted, new ParallelOptions { MaxDegreeOfParallelism = this.MaxDegreeOfParallelism }, (task, state) => this.Worker(exceptions, state, task));

if (this.FailOnError && exceptions.Any())
{
throw new BuildException("Parallel worker failed!", new AggregateException(exceptions));
}
}

[TaskAttribute("FailFast")]
public bool FailFast
{
get;
set;
}

[TaskAttribute("MaxDegreeOfParallelism")]
public int MaxDegreeOfParallelism
{
get;
set;
}

[BuildElement("call", Required = true)]
public void AddExec(CallTask task)
{
task.Parent = this;

this.tasksToBeExecuted.Add(task);
}

private void Worker(ConcurrentQueue<Exception> exceptions, ParallelLoopState state, CallTask task)
{
try
{
task.Execute();
}
catch (Exception e)
{
Log(this.FailOnError ? Level.Error : Level.Debug, "Exception on parallel worker: {0}\r\n{3}\r\nFailOnError: {1} / FailFast: {2}", e.Message, this.FailOnError, this.FailFast, e.StackTrace);

exceptions.Enqueue(e);

if (this.FailFast)
{
state.Break();
}
}
}
}
code

and here the usage

code
    <target name="tests" description="run tests and specs in parallel">
        <asynccall FailFast="true" MaxDegreeOfParallelism="4">
            <call target="unit-tests" />
            <call target="specifications" />
        </asynccall>
    </target>

I first thought it is related to TeamCity's task patching but the problem is that TaskBuilderCollection.Item[] is not thread safe. 

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=402868&aid=3451075&group_id=31650

------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure 
contains a definitive record of customers, application performance, 
security threats, fraudulent activity, and more. Splunk takes this 
data and makes sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-novd2d