Browse Source

BuildWorker: swap communication and build threads.

This is an attempt to fix http://community.sharpdevelop.net/forums/t/15654.aspx - BuildWorker40 hangs on windows 7 x64bit when invoking the markup compiler.
According the the report in the forums, the problem disappears when MSBuild is invoked on the main thread, and communication is suspended while the build is in progress (breaking cancellation).
This patch also moves the communication onto a background thread, fixing build cancellation. This might solve the problem if the hang was somehow related to the thread MSBuild was running on. However, if the AppDomain unload fails due to the thread stuck reading from the named pipe, the build worker might continue hanging with this patch.
4.2
Daniel Grunwald 13 years ago
parent
commit
bbd58339cd
  1. 55
      src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs

55
src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs

@ -18,9 +18,10 @@ namespace ICSharpCode.SharpDevelop.BuildWorker
{ {
sealed class Program sealed class Program
{ {
static HostProcess host; HostProcess host;
BuildJob currentJob; BuildJob currentJob;
bool requestCancellation; bool requestCancellation;
bool requestProcessShutdown;
[STAThread] [STAThread]
internal static void Main(string[] args) internal static void Main(string[] args)
@ -29,8 +30,12 @@ namespace ICSharpCode.SharpDevelop.BuildWorker
if (args.Length == 3 && args[0] == "worker") { if (args.Length == 3 && args[0] == "worker") {
try { try {
host = new HostProcess(args[1], args[2]); Program program = new Program();
host.Run(new Program().DataReceived); program.host = new HostProcess(args[1], args[2]);
Thread communicationThread = new Thread(program.RunCommunicationThread);
communicationThread.Name = "Communication";
communicationThread.Start();
program.RunBuildThread();
} catch (Exception ex) { } catch (Exception ex) {
ShowMessageBox(ex.ToString()); ShowMessageBox(ex.ToString());
} }
@ -42,10 +47,25 @@ namespace ICSharpCode.SharpDevelop.BuildWorker
} }
} }
void RunCommunicationThread()
{
try {
host.Run(DataReceived);
} catch (Exception ex) {
ShowMessageBox(ex.ToString());
} finally {
lock (this) {
requestProcessShutdown = true;
Monitor.PulseAll(this);
}
}
}
readonly MSBuildWrapper buildWrapper = new MSBuildWrapper(); readonly MSBuildWrapper buildWrapper = new MSBuildWrapper();
void DataReceived(string command, BinaryReader reader) void DataReceived(string command, BinaryReader reader)
{ {
// called on communication thread
switch (command) { switch (command) {
case "StartBuild": case "StartBuild":
StartBuild(BuildJob.ReadFrom(reader)); StartBuild(BuildJob.ReadFrom(reader));
@ -86,28 +106,26 @@ namespace ICSharpCode.SharpDevelop.BuildWorker
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
public void StartBuild(BuildJob job) public void StartBuild(BuildJob job)
{ {
// called on communication thread
if (job == null) if (job == null)
throw new ArgumentNullException("job"); throw new ArgumentNullException("job");
Program.Log("Got job:");
Program.Log(job.ToString());
lock (this) { lock (this) {
if (currentJob != null) if (currentJob != null)
throw new InvalidOperationException("Already running a job"); throw new InvalidOperationException("Already running a job");
currentJob = job; currentJob = job;
requestCancellation = false; requestCancellation = false;
Monitor.PulseAll(this);
} }
#if WORKERDEBUG #if WORKERDEBUG
Console.Title = "BuildWorker - " + Path.GetFileName(job.ProjectFileName); Console.Title = "BuildWorker - " + Path.GetFileName(job.ProjectFileName);
#endif #endif
Program.Log("Got job:");
Program.Log(job.ToString());
Program.Log("Start build thread");
Thread thread = new Thread(RunThread);
thread.Name = "Build thread";
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
} }
public void CancelBuild() public void CancelBuild()
{ {
// called on communication thread
Program.Log("CancelBuild()"); Program.Log("CancelBuild()");
lock (this) { lock (this) {
if (!requestCancellation) { if (!requestCancellation) {
@ -117,8 +135,21 @@ namespace ICSharpCode.SharpDevelop.BuildWorker
} }
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] void RunBuildThread()
void RunThread() {
while (true) {
// Wait for next job, or for shutdown
lock (this) {
while (currentJob == null && !requestProcessShutdown)
Monitor.Wait(this);
if (requestProcessShutdown)
break;
}
PerformBuild();
}
}
void PerformBuild()
{ {
Program.Log("In build thread"); Program.Log("In build thread");
bool success = false; bool success = false;

Loading…
Cancel
Save