PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/Microsoft.Build/Microsoft.Build/Microsoft/Build/BackEnd/RequestBuilder.cs

#
C# | 671 lines | 638 code | 33 blank | 0 comment | 109 complexity | a1441d8d0d1d4af9d32bcf53c0483534 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-3.0
  1. namespace Microsoft.Build.BackEnd
  2. {
  3. using Microsoft.Build.BackEnd.Logging;
  4. using Microsoft.Build.Collections;
  5. using Microsoft.Build.Evaluation;
  6. using Microsoft.Build.Exceptions;
  7. using Microsoft.Build.Execution;
  8. using Microsoft.Build.Framework;
  9. using Microsoft.Build.Internal;
  10. using Microsoft.Build.Shared;
  11. using Microsoft.Internal.Performance;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.IO;
  15. using System.Runtime;
  16. using System.Threading;
  17. internal class RequestBuilder : IRequestBuilder, IRequestBuilderCallback, IBuildComponent
  18. {
  19. private BlockType blockType = BlockType.Unblocked;
  20. private object buildStateLock = new object();
  21. private IBuildComponentHost componentHost;
  22. private AutoResetEvent continueEvent = new AutoResetEvent(false);
  23. private IDictionary<int, BuildResult> continueResults;
  24. private NodeLoggingContext nodeLoggingContext;
  25. private BuildRequestBlockedDelegate OnBuildRequestBlocked;
  26. private BuildRequestCompletedDelegate OnBuildRequestCompleted;
  27. private NewBuildRequestsDelegate OnNewBuildRequests;
  28. private ProjectLoggingContext projectLoggingContext;
  29. private ManualResetEvent requestBuilderIdle = new ManualResetEvent(true);
  30. private BuildRequestEntry requestEntry;
  31. private Thread requestThread;
  32. private string savedCurrentDirectory;
  33. private IDictionary<string, string> savedEnvironmentVariables;
  34. private AutoResetEvent shutdownThreadEvent = new AutoResetEvent(false);
  35. private AutoResetEvent startBuildingEvent = new AutoResetEvent(false);
  36. private ITargetBuilder targetBuilder;
  37. private ManualResetEvent terminateEvent = new ManualResetEvent(false);
  38. public event BuildRequestBlockedDelegate OnBuildRequestBlocked
  39. {
  40. add
  41. {
  42. BuildRequestBlockedDelegate delegate3;
  43. BuildRequestBlockedDelegate onBuildRequestBlocked = this.OnBuildRequestBlocked;
  44. do
  45. {
  46. delegate3 = onBuildRequestBlocked;
  47. BuildRequestBlockedDelegate delegate4 = (BuildRequestBlockedDelegate) Delegate.Combine(delegate3, value);
  48. onBuildRequestBlocked = Interlocked.CompareExchange<BuildRequestBlockedDelegate>(ref this.OnBuildRequestBlocked, delegate4, delegate3);
  49. }
  50. while (onBuildRequestBlocked != delegate3);
  51. }
  52. remove
  53. {
  54. BuildRequestBlockedDelegate delegate3;
  55. BuildRequestBlockedDelegate onBuildRequestBlocked = this.OnBuildRequestBlocked;
  56. do
  57. {
  58. delegate3 = onBuildRequestBlocked;
  59. BuildRequestBlockedDelegate delegate4 = (BuildRequestBlockedDelegate) Delegate.Remove(delegate3, value);
  60. onBuildRequestBlocked = Interlocked.CompareExchange<BuildRequestBlockedDelegate>(ref this.OnBuildRequestBlocked, delegate4, delegate3);
  61. }
  62. while (onBuildRequestBlocked != delegate3);
  63. }
  64. }
  65. public event BuildRequestCompletedDelegate OnBuildRequestCompleted
  66. {
  67. add
  68. {
  69. BuildRequestCompletedDelegate delegate3;
  70. BuildRequestCompletedDelegate onBuildRequestCompleted = this.OnBuildRequestCompleted;
  71. do
  72. {
  73. delegate3 = onBuildRequestCompleted;
  74. BuildRequestCompletedDelegate delegate4 = (BuildRequestCompletedDelegate) Delegate.Combine(delegate3, value);
  75. onBuildRequestCompleted = Interlocked.CompareExchange<BuildRequestCompletedDelegate>(ref this.OnBuildRequestCompleted, delegate4, delegate3);
  76. }
  77. while (onBuildRequestCompleted != delegate3);
  78. }
  79. remove
  80. {
  81. BuildRequestCompletedDelegate delegate3;
  82. BuildRequestCompletedDelegate onBuildRequestCompleted = this.OnBuildRequestCompleted;
  83. do
  84. {
  85. delegate3 = onBuildRequestCompleted;
  86. BuildRequestCompletedDelegate delegate4 = (BuildRequestCompletedDelegate) Delegate.Remove(delegate3, value);
  87. onBuildRequestCompleted = Interlocked.CompareExchange<BuildRequestCompletedDelegate>(ref this.OnBuildRequestCompleted, delegate4, delegate3);
  88. }
  89. while (onBuildRequestCompleted != delegate3);
  90. }
  91. }
  92. public event NewBuildRequestsDelegate OnNewBuildRequests
  93. {
  94. add
  95. {
  96. NewBuildRequestsDelegate delegate3;
  97. NewBuildRequestsDelegate onNewBuildRequests = this.OnNewBuildRequests;
  98. do
  99. {
  100. delegate3 = onNewBuildRequests;
  101. NewBuildRequestsDelegate delegate4 = (NewBuildRequestsDelegate) Delegate.Combine(delegate3, value);
  102. onNewBuildRequests = Interlocked.CompareExchange<NewBuildRequestsDelegate>(ref this.OnNewBuildRequests, delegate4, delegate3);
  103. }
  104. while (onNewBuildRequests != delegate3);
  105. }
  106. remove
  107. {
  108. NewBuildRequestsDelegate delegate3;
  109. NewBuildRequestsDelegate onNewBuildRequests = this.OnNewBuildRequests;
  110. do
  111. {
  112. delegate3 = onNewBuildRequests;
  113. NewBuildRequestsDelegate delegate4 = (NewBuildRequestsDelegate) Delegate.Remove(delegate3, value);
  114. onNewBuildRequests = Interlocked.CompareExchange<NewBuildRequestsDelegate>(ref this.OnNewBuildRequests, delegate4, delegate3);
  115. }
  116. while (onNewBuildRequests != delegate3);
  117. }
  118. }
  119. internal RequestBuilder()
  120. {
  121. }
  122. public void BlockOnTargetInProgress(int blockingGlobalRequestId, string blockingTarget)
  123. {
  124. this.SaveOperatingEnvironment();
  125. this.blockType = BlockType.BlockedOnTargetInProgress;
  126. this.RaiseOnBlockedRequest(blockingGlobalRequestId, blockingTarget);
  127. int num = WaitHandle.WaitAny(new WaitHandle[] { this.shutdownThreadEvent, this.terminateEvent, this.continueEvent });
  128. this.RestoreOperatingEnvironment();
  129. switch (num)
  130. {
  131. case 0:
  132. case 1:
  133. throw new BuildAbortedException();
  134. }
  135. this.blockType = BlockType.Unblocked;
  136. this.VerifyEntryInActiveState();
  137. }
  138. private void BuildAndReport()
  139. {
  140. Exception exception = null;
  141. BuildResult result = null;
  142. try
  143. {
  144. this.VerifyEntryInActiveState();
  145. result = this.BuildProject();
  146. }
  147. catch (InvalidProjectFileException exception2)
  148. {
  149. if (this.projectLoggingContext != null)
  150. {
  151. this.projectLoggingContext.LogInvalidProjectFileError(exception2);
  152. }
  153. else
  154. {
  155. this.nodeLoggingContext.LogInvalidProjectFileError(exception2);
  156. }
  157. exception = exception2;
  158. }
  159. catch (LoggerException exception3)
  160. {
  161. exception = exception3;
  162. }
  163. catch (InternalLoggerException exception4)
  164. {
  165. exception = exception4;
  166. }
  167. catch (ThreadAbortException)
  168. {
  169. exception = new BuildAbortedException();
  170. Thread.ResetAbort();
  171. }
  172. catch (Exception exception5)
  173. {
  174. exception = exception5;
  175. if (ExceptionHandling.IsCriticalException(exception5))
  176. {
  177. throw;
  178. }
  179. }
  180. finally
  181. {
  182. lock (this.buildStateLock)
  183. {
  184. this.blockType = BlockType.Unblocked;
  185. if (exception != null)
  186. {
  187. ErrorUtilities.VerifyThrow(result == null, "Result already set when exception was thrown.");
  188. result = new BuildResult(this.requestEntry.Request, exception);
  189. }
  190. if (this.projectLoggingContext != null)
  191. {
  192. this.projectLoggingContext.LogProjectFinished(result.OverallResult == BuildResultCode.Success);
  193. }
  194. BuildRequestEntry requestEntry = this.requestEntry;
  195. this.nodeLoggingContext = null;
  196. this.requestEntry = null;
  197. this.targetBuilder = null;
  198. this.requestBuilderIdle.Set();
  199. requestEntry.Complete(result);
  200. this.RaiseBuildRequestCompleted(requestEntry);
  201. }
  202. }
  203. }
  204. private BuildResult BuildProject()
  205. {
  206. ErrorUtilities.VerifyThrow(this.targetBuilder != null, "Target builder is null");
  207. this.projectLoggingContext = null;
  208. try
  209. {
  210. if (!this.requestEntry.RequestConfiguration.IsLoaded)
  211. {
  212. this.LoadProjectIntoConfiguration();
  213. }
  214. }
  215. catch
  216. {
  217. this.projectLoggingContext = new ProjectLoggingContext(this.nodeLoggingContext, this.requestEntry.Request, this.requestEntry.RequestConfiguration.ProjectFullPath, this.requestEntry.RequestConfiguration.ToolsVersion, this.requestEntry.Request.ParentBuildEventContext);
  218. throw;
  219. }
  220. this.projectLoggingContext = this.nodeLoggingContext.LogProjectStarted(this.requestEntry);
  221. this.requestEntry.RequestConfiguration.RetrieveFromCache();
  222. if (this.requestEntry.RequestConfiguration.Project.TreatingHigherToolsVersionsAs40)
  223. {
  224. this.projectLoggingContext.LogComment(MessageImportance.High, "TreatingHigherToolsVersionAs40", new object[] { this.requestEntry.RequestConfiguration.Project.OriginalProjectToolsVersion });
  225. }
  226. this.requestEntry.Request.BuildEventContext = this.projectLoggingContext.BuildEventContext;
  227. string[] targets = this.requestEntry.RequestConfiguration.GetTargetsUsedToBuildRequest(this.requestEntry.Request).ToArray();
  228. ProjectErrorUtilities.VerifyThrowInvalidProject(targets.Length > 0, this.requestEntry.RequestConfiguration.Project.ProjectFileLocation, "NoTargetSpecified");
  229. this.SetProjectCurrentDirectory();
  230. return this.targetBuilder.BuildTargets(this.projectLoggingContext, this.requestEntry, this, targets, this.requestEntry.RequestConfiguration.BaseLookup);
  231. }
  232. public BuildResult[] BuildProjects(string[] projectFiles, PropertyDictionary<ProjectPropertyInstance>[] properties, string[] toolsVersions, string[] targets, bool waitForResults)
  233. {
  234. ErrorUtilities.VerifyThrowArgumentNull(projectFiles, "projectFiles");
  235. ErrorUtilities.VerifyThrowArgumentNull(properties, "properties");
  236. ErrorUtilities.VerifyThrowArgumentNull(targets, "targets");
  237. ErrorUtilities.VerifyThrowArgumentNull(toolsVersions, "toolsVersions");
  238. ErrorUtilities.VerifyThrow(this.componentHost != null, "No host object set");
  239. ErrorUtilities.VerifyThrow(projectFiles.Length == properties.Length, "Properties and project counts not the same");
  240. ErrorUtilities.VerifyThrow(projectFiles.Length == toolsVersions.Length, "Tools versions and project counts not the same");
  241. FullyQualifiedBuildRequest[] requests = new FullyQualifiedBuildRequest[projectFiles.Length];
  242. for (int i = 0; i < projectFiles.Length; i++)
  243. {
  244. if (!Path.IsPathRooted(projectFiles[i]))
  245. {
  246. projectFiles[i] = Path.Combine(this.requestEntry.ProjectRootDirectory, projectFiles[i]);
  247. }
  248. projectFiles[i] = FileUtilities.NormalizePath(projectFiles[i]);
  249. string toolsVersion = toolsVersions[i];
  250. if ((toolsVersion == null) && this.requestEntry.RequestConfiguration.ExplicitToolsVersionSpecified)
  251. {
  252. toolsVersion = this.requestEntry.RequestConfiguration.ToolsVersion;
  253. }
  254. BuildRequestData data = new BuildRequestData(projectFiles[i], properties[i].ToDictionary(), toolsVersion, targets, null);
  255. BuildRequestConfiguration config = new BuildRequestConfiguration(data, this.componentHost.BuildParameters.DefaultToolsVersion);
  256. requests[i] = new FullyQualifiedBuildRequest(config, targets, waitForResults);
  257. }
  258. List<BuildResult> list = new List<BuildResult>(this.StartNewBuildRequests(requests).Values);
  259. list.Sort(delegate (BuildResult left, BuildResult right) {
  260. if (left.NodeRequestId < right.NodeRequestId)
  261. {
  262. return -1;
  263. }
  264. if (left.NodeRequestId == right.NodeRequestId)
  265. {
  266. return 0;
  267. }
  268. return 1;
  269. });
  270. return list.ToArray();
  271. }
  272. public void BuildRequest(NodeLoggingContext loggingContext, BuildRequestEntry entry)
  273. {
  274. lock (this.buildStateLock)
  275. {
  276. ErrorUtilities.VerifyThrowArgumentNull(loggingContext, "loggingContext");
  277. ErrorUtilities.VerifyThrowArgumentNull(entry, "entry");
  278. ErrorUtilities.VerifyThrow(null != this.componentHost, "Host not set.");
  279. ErrorUtilities.VerifyThrow(this.requestBuilderIdle.WaitOne(0, false), "Build in progress.");
  280. ErrorUtilities.VerifyThrow(this.targetBuilder == null, "targetBuilder not null");
  281. ErrorUtilities.VerifyThrow(this.nodeLoggingContext == null, "nodeLoggingContext not null");
  282. ErrorUtilities.VerifyThrow(this.requestEntry == null, "requestEntry not null");
  283. this.nodeLoggingContext = loggingContext;
  284. this.blockType = BlockType.Unblocked;
  285. this.requestEntry = entry;
  286. this.requestEntry.Continue();
  287. this.targetBuilder = (ITargetBuilder) this.componentHost.GetComponent(BuildComponentType.TargetBuilder);
  288. this.VerifyEntryInActiveState();
  289. if (this.componentHost.BuildParameters.LegacyThreadingSemantics && (this.componentHost.LegacyThreadingData.MainThreadSubmissionId == this.requestEntry.Request.SubmissionId))
  290. {
  291. if (this.requestThread != null)
  292. {
  293. this.shutdownThreadEvent.Set();
  294. this.requestThread.Join();
  295. this.requestThread = null;
  296. }
  297. this.continueResults = null;
  298. this.componentHost.LegacyThreadingData.InstanceForMainThread = this;
  299. this.componentHost.LegacyThreadingData.StartNewRequestBuilderMainThreadEvent.Set();
  300. }
  301. else
  302. {
  303. if (this.requestThread == null)
  304. {
  305. this.requestThread = new Thread(new ThreadStart(this.RequestThreadProc));
  306. this.requestThread.Name = "RequestBuilder thread";
  307. this.requestThread.IsBackground = true;
  308. this.requestThread.Priority = this.componentHost.BuildParameters.BuildThreadPriority;
  309. if (Environment.GetEnvironmentVariable("MSBUILDFORCESTA") == "1")
  310. {
  311. this.requestThread.SetApartmentState(ApartmentState.STA);
  312. }
  313. else
  314. {
  315. this.requestThread.SetApartmentState(ApartmentState.MTA);
  316. }
  317. this.continueResults = null;
  318. this.requestThread.Start();
  319. }
  320. this.requestThread.CurrentCulture = this.componentHost.BuildParameters.Culture;
  321. this.requestThread.CurrentUICulture = this.componentHost.BuildParameters.UICulture;
  322. ErrorUtilities.VerifyThrow(this.requestThread.IsAlive, "RequestBuilder thread is not alive. ManagedThreadId: {0}", this.requestThread.ManagedThreadId);
  323. }
  324. this.requestBuilderIdle.Reset();
  325. this.startBuildingEvent.Set();
  326. }
  327. }
  328. public void CancelRequest()
  329. {
  330. ITargetBuilder targetBuilder;
  331. lock (this.buildStateLock)
  332. {
  333. if ((this.requestEntry == null) || (this.targetBuilder == null))
  334. {
  335. return;
  336. }
  337. ErrorUtilities.VerifyThrow((this.requestThread != null) || (this.componentHost.LegacyThreadingData.MainThreadSubmissionId != -1), "Request thread not set");
  338. targetBuilder = this.targetBuilder;
  339. ErrorUtilities.VerifyThrow(!this.terminateEvent.WaitOne(0, false), "Request already terminated");
  340. this.terminateEvent.Set();
  341. }
  342. try
  343. {
  344. targetBuilder.CancelRequest();
  345. if (!this.requestBuilderIdle.WaitOne(BuildParameters.RequestBuilderShutdownTimeout))
  346. {
  347. this.projectLoggingContext.LogError(new BuildEventFileInfo(string.Empty), "FailedToReceiveTaskThreadStatus", new object[] { BuildParameters.RequestBuilderShutdownTimeout });
  348. ErrorUtilities.ThrowInvalidOperation("UnableToCancel", new object[0]);
  349. }
  350. }
  351. finally
  352. {
  353. this.terminateEvent.Reset();
  354. }
  355. }
  356. public void ContinueRequest()
  357. {
  358. ErrorUtilities.VerifyThrow((this.requestThread != null) || (this.componentHost.LegacyThreadingData.MainThreadSubmissionId != -1), "Request not building");
  359. ErrorUtilities.VerifyThrow(!this.terminateEvent.WaitOne(0, false), "Request already terminated");
  360. ErrorUtilities.VerifyThrow(!this.continueEvent.WaitOne(0, false), "Request already continued");
  361. this.VerifyEntryInReadyState();
  362. this.continueResults = this.requestEntry.Continue();
  363. ErrorUtilities.VerifyThrow(((this.blockType == BlockType.BlockedOnTargetInProgress) || (this.blockType == BlockType.Yielded)) || (this.continueResults != null), "Unexpected null results for request {0} (nr {1})", this.requestEntry.Request.GlobalRequestId, this.requestEntry.Request.NodeRequestId);
  364. this.continueEvent.Set();
  365. }
  366. internal static IBuildComponent CreateComponent(BuildComponentType type)
  367. {
  368. ErrorUtilities.VerifyThrow(type == BuildComponentType.RequestBuilder, "Cannot create components of type {0}", type);
  369. return new RequestBuilder();
  370. }
  371. public void InitializeComponent(IBuildComponentHost host)
  372. {
  373. ErrorUtilities.VerifyThrowArgumentNull(host, "host");
  374. ErrorUtilities.VerifyThrow(this.componentHost == null, "RequestBuilder already initialized.");
  375. this.componentHost = host;
  376. }
  377. private void LoadProjectIntoConfiguration()
  378. {
  379. ErrorUtilities.VerifyThrow(this.requestEntry.RequestConfiguration.Project == null, "We've already loaded the project for this configuration id {0}.", this.requestEntry.RequestConfiguration.ConfigurationId);
  380. if (this.componentHost.BuildParameters.SaveOperatingEnvironment)
  381. {
  382. Directory.SetCurrentDirectory(BuildParameters.StartupDirectory);
  383. }
  384. Dictionary<string, string> globalProperties = new Dictionary<string, string>(MSBuildNameIgnoreCaseComparer.Default);
  385. foreach (ProjectPropertyInstance instance in this.requestEntry.RequestConfiguration.Properties)
  386. {
  387. globalProperties.Add(instance.Name, ((IProperty) instance).EvaluatedValueEscaped);
  388. }
  389. string toolsVersion = this.requestEntry.RequestConfiguration.ExplicitToolsVersionSpecified ? this.requestEntry.RequestConfiguration.ToolsVersion : null;
  390. this.requestEntry.RequestConfiguration.Project = new ProjectInstance(this.requestEntry.RequestConfiguration.ProjectFullPath, globalProperties, toolsVersion, this.componentHost.BuildParameters, this.nodeLoggingContext.LoggingService, this.requestEntry.Request.BuildEventContext);
  391. }
  392. private void RaiseBuildRequestCompleted(BuildRequestEntry entryToComplete)
  393. {
  394. BuildRequestCompletedDelegate onBuildRequestCompleted = this.OnBuildRequestCompleted;
  395. if (onBuildRequestCompleted != null)
  396. {
  397. onBuildRequestCompleted(entryToComplete);
  398. }
  399. }
  400. private void RaiseOnBlockedRequest(int blockingGlobalRequestId, string blockingTarget)
  401. {
  402. BuildRequestBlockedDelegate onBuildRequestBlocked = this.OnBuildRequestBlocked;
  403. if (onBuildRequestBlocked != null)
  404. {
  405. onBuildRequestBlocked(this.requestEntry, blockingGlobalRequestId, blockingTarget);
  406. }
  407. }
  408. private void RaiseOnNewBuildRequests(FullyQualifiedBuildRequest[] requests)
  409. {
  410. NewBuildRequestsDelegate onNewBuildRequests = this.OnNewBuildRequests;
  411. if (onNewBuildRequests != null)
  412. {
  413. onNewBuildRequests(this.requestEntry, requests);
  414. }
  415. }
  416. public void Reacquire()
  417. {
  418. this.RaiseOnBlockedRequest(this.requestEntry.Request.GlobalRequestId, string.Empty);
  419. int num = WaitHandle.WaitAny(new WaitHandle[] { this.shutdownThreadEvent, this.terminateEvent, this.continueEvent });
  420. this.RestoreOperatingEnvironment();
  421. switch (num)
  422. {
  423. case 0:
  424. case 1:
  425. throw new BuildAbortedException();
  426. }
  427. this.blockType = BlockType.Unblocked;
  428. this.VerifyEntryInActiveState();
  429. }
  430. private void RequestThreadProc()
  431. {
  432. try
  433. {
  434. bool flag = false;
  435. WaitHandle[] waitHandles = new WaitHandle[] { this.shutdownThreadEvent, this.startBuildingEvent };
  436. while (!flag)
  437. {
  438. switch (WaitHandle.WaitAny(waitHandles))
  439. {
  440. case 0:
  441. flag = true;
  442. break;
  443. case 1:
  444. using (new Microsoft.Internal.Performance.CodeMarkerStartEnd(Microsoft.Internal.Performance.CodeMarkerEvent.perfMSBuildEngineBuildProjectBegin, Microsoft.Internal.Performance.CodeMarkerEvent.perfMSBuildEngineBuildProjectEnd))
  445. {
  446. this.BuildAndReport();
  447. if (this.requestThread == null)
  448. {
  449. flag = true;
  450. }
  451. }
  452. break;
  453. }
  454. }
  455. }
  456. catch (ThreadAbortException)
  457. {
  458. throw;
  459. }
  460. catch (Exception exception)
  461. {
  462. ExceptionHandling.DumpExceptionToFile(exception);
  463. ErrorUtilities.ThrowInternalError(exception.Message, exception, new object[0]);
  464. throw;
  465. }
  466. }
  467. private void RestoreOperatingEnvironment()
  468. {
  469. if (this.componentHost.BuildParameters.SaveOperatingEnvironment)
  470. {
  471. ErrorUtilities.VerifyThrow(this.savedCurrentDirectory != null, "Current directory not previously saved.");
  472. ErrorUtilities.VerifyThrow(this.savedEnvironmentVariables != null, "Current environment not previously saved.");
  473. IDictionary<string, string> environmentVariables = Utilities.GetEnvironmentVariables();
  474. foreach (KeyValuePair<string, string> pair in environmentVariables)
  475. {
  476. if (!this.savedEnvironmentVariables.ContainsKey(pair.Key))
  477. {
  478. Environment.SetEnvironmentVariable(pair.Key, null);
  479. }
  480. }
  481. foreach (KeyValuePair<string, string> pair2 in this.savedEnvironmentVariables)
  482. {
  483. string str;
  484. if (!environmentVariables.TryGetValue(pair2.Key, out str) || !string.Equals(pair2.Value, str, StringComparison.Ordinal))
  485. {
  486. Environment.SetEnvironmentVariable(pair2.Key, pair2.Value);
  487. }
  488. }
  489. NativeMethodsShared.SetCurrentDirectory(this.savedCurrentDirectory);
  490. }
  491. this.savedEnvironmentVariables = null;
  492. this.savedCurrentDirectory = null;
  493. }
  494. private void SaveOperatingEnvironment()
  495. {
  496. if (this.componentHost.BuildParameters.SaveOperatingEnvironment)
  497. {
  498. this.savedCurrentDirectory = NativeMethodsShared.GetCurrentDirectory();
  499. this.savedEnvironmentVariables = Utilities.GetEnvironmentVariables();
  500. }
  501. }
  502. private void SetProjectCurrentDirectory()
  503. {
  504. if (this.componentHost.BuildParameters.SaveOperatingEnvironment)
  505. {
  506. NativeMethodsShared.SetCurrentDirectory(this.requestEntry.ProjectRootDirectory);
  507. }
  508. }
  509. public void ShutdownComponent()
  510. {
  511. this.shutdownThreadEvent.Set();
  512. if (this.requestThread != null)
  513. {
  514. ErrorUtilities.VerifyThrow(this.requestThread.Join(BuildParameters.RequestBuilderShutdownTimeout), "Request thread not terminated before shutdown.");
  515. }
  516. this.componentHost = null;
  517. }
  518. private IDictionary<int, BuildResult> StartNewBuildRequests(FullyQualifiedBuildRequest[] requests)
  519. {
  520. IDictionary<int, BuildResult> continueResults;
  521. bool flag = false;
  522. foreach (FullyQualifiedBuildRequest request in requests)
  523. {
  524. if (request.ResultsNeeded)
  525. {
  526. flag = true;
  527. break;
  528. }
  529. }
  530. this.blockType = BlockType.BlockedOnChildRequests;
  531. if (flag)
  532. {
  533. this.SaveOperatingEnvironment();
  534. }
  535. this.continueResults = null;
  536. this.RaiseOnNewBuildRequests(requests);
  537. if (flag)
  538. {
  539. int num;
  540. WaitHandle[] handles = new WaitHandle[] { this.shutdownThreadEvent, this.terminateEvent, this.continueEvent };
  541. if (this.requestThread == null)
  542. {
  543. num = WaitWithBuilderThreadStart(handles, true, this.componentHost.LegacyThreadingData);
  544. }
  545. else
  546. {
  547. num = WaitHandle.WaitAny(handles);
  548. }
  549. if (num == 2)
  550. {
  551. this.RestoreOperatingEnvironment();
  552. this.VerifyEntryInActiveState();
  553. }
  554. continueResults = this.continueResults;
  555. this.continueResults = null;
  556. if (continueResults == null)
  557. {
  558. ErrorUtilities.VerifyThrow((num == 0) || (num == 1), "Unexpected null results during continue");
  559. continueResults = new Dictionary<int, BuildResult>();
  560. for (int i = 0; i < requests.Length; i++)
  561. {
  562. continueResults[i] = new BuildResult(new Microsoft.Build.BackEnd.BuildRequest(), new BuildAbortedException());
  563. }
  564. }
  565. foreach (BuildResult result in continueResults.Values)
  566. {
  567. if (result.CircularDependency)
  568. {
  569. throw new CircularDependencyException();
  570. }
  571. }
  572. }
  573. else
  574. {
  575. continueResults = new Dictionary<int, BuildResult>();
  576. }
  577. this.blockType = BlockType.Unblocked;
  578. return continueResults;
  579. }
  580. private void VerifyEntryInActiveState()
  581. {
  582. ErrorUtilities.VerifyThrow(this.requestEntry.State == BuildRequestEntryState.Active, "Entry is not in the Active state, it is in the {0} state.", this.requestEntry.State);
  583. }
  584. private void VerifyEntryInReadyState()
  585. {
  586. ErrorUtilities.VerifyThrow(this.requestEntry.State == BuildRequestEntryState.Ready, "Entry is not in the Ready state, it is in the {0} state.", this.requestEntry.State);
  587. }
  588. internal static int WaitWithBuilderThreadStart(WaitHandle[] handles, bool recursive, LegacyThreadingData threadingData)
  589. {
  590. int num2;
  591. WaitHandle[] destinationArray = new WaitHandle[handles.Length + 1];
  592. destinationArray[0] = threadingData.StartNewRequestBuilderMainThreadEvent;
  593. Array.Copy(handles, 0, destinationArray, 1, handles.Length);
  594. Label_0020:;
  595. try
  596. {
  597. int num = ThreadingUtilities.WaitAnyNoMessagePump(destinationArray, -1);
  598. if (num == 0)
  599. {
  600. RequestBuilder instanceForMainThread = threadingData.InstanceForMainThread;
  601. threadingData.InstanceForMainThread = null;
  602. instanceForMainThread.RequestThreadProc();
  603. goto Label_0020;
  604. }
  605. num2 = num - 1;
  606. }
  607. finally
  608. {
  609. if (!recursive)
  610. {
  611. threadingData.MainThreadSubmissionId = -1;
  612. }
  613. }
  614. return num2;
  615. }
  616. public void Yield()
  617. {
  618. this.SaveOperatingEnvironment();
  619. this.blockType = BlockType.Yielded;
  620. this.RaiseOnBlockedRequest(this.requestEntry.Request.GlobalRequestId, null);
  621. }
  622. internal BuildRequestEntry RequestEntry
  623. {
  624. [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  625. get
  626. {
  627. return this.requestEntry;
  628. }
  629. }
  630. private enum BlockType
  631. {
  632. BlockedOnTargetInProgress,
  633. BlockedOnChildRequests,
  634. Yielded,
  635. Unblocked
  636. }
  637. }
  638. }