Skip to content

Commit

Permalink
Retry apphost creation.
Browse files Browse the repository at this point in the history
This commit implements a parameterized retry count for creating the apphost.

Like the `Copy` task from MSBuild, the `CreateAppHost` task now takes a
parameter to specify the number of retries and the delay between retries (in
milliseconds) to perform if the creation fails.

This should help alleviate build failures when external processes are locking
the intermediate apphost during a build (especially on Windows).

Fixes devdiv#950462.
Fixes dotnet/cli#11650.
  • Loading branch information
Peter Huene committed Aug 6, 2019
1 parent 4f452f6 commit 82e4029
Show file tree
Hide file tree
Showing 17 changed files with 175 additions and 19 deletions.
4 changes: 4 additions & 0 deletions src/Tasks/Common/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -556,4 +556,8 @@ The following are names of parameters or literal values and should not be transl
<value>NETSDK1112: The runtime pack for {0} was not downloaded. Try running a NuGet restore with the RuntimeIdentifier '{1}'.</value>
<comment>{StrBegin="NETSDK1112: "}</comment>
</data>
<data name="AppHostCreationFailedWithRetry" xml:space="preserve">
<value>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</value>
<comment>{StrBegin="NETSDK1113: "}</comment>
</data>
</root>
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: Konfigurační soubor aplikace musí obsahovat kořenový element konfigurace.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: Spustitelný soubor hostitele aplikace se nepřizpůsobí, protože přidávání prostředků vyžaduje, aby se sestavení provedlo na Windows (bez Nano Serveru).</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: Die Anwendungskonfigurationsdatei muss das Stammkonfigurationselement enthalten.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: Die ausführbare Anwendungshostdatei wird nicht angepasst, weil für das Hinzufügen von Ressourcen eine Ausführung des Builds unter Windows erforderlich ist (Nano Server ausgeschlossen).</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: El archivo de configuración de la aplicación debe tener el elemento de configuración raíz.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: El ejecutable del host de aplicación no se personalizará porque para agregar recursos es necesario que la compilación se realice en Windows (excepto Nano Server).</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: Le fichier de configuration de l'application doit avoir un élément de configuration racine.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: l'exécutable d'hôte d'application ne sera pas personnalisé, car l'ajout de ressources nécessite l'exécution de la génération sur Windows (à l'exception de Nano Server).</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: il file di configurazione dell'applicazione deve avere un elemento di configurazione radice.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: l'eseguibile dell'host applicazione non verrà personalizzato perché per aggiungere risorse è necessario eseguire la compilazione in Windows (escluso Nano Server).</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: アプリケーション構成ファイルには、ルート構成要素が必要です。</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: リソースの追加ではビルドが Windows 上で実行される必要があるため、アプリケーション ホストの実行可能ファイルはカスタマイズされません (Nano Server を除く)。</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: 애플리케이션 구성 파일에는 루트 구성 요소가 있어야 합니다.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: 리소스를 추가하려면 빌드가 Windows(Nano Server 제외)에서 수행되어야 하므로 애플리케이션 호스트 실행 파일이 사용자 지정되지 않습니다.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: Plik konfiguracji aplikacji musi mieć główny element konfiguracji.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: Plik wykonywalny hosta aplikacji nie zostanie dostosowany, ponieważ dodawanie zasobów wymaga, aby kompilacja została wykonana w systemie Windows (z wyjątkiem systemu Nano Server).</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: o arquivo de configuração do aplicativo deve ter um elemento de configuração raiz.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: o host do aplicativo executável não será personalizado porque a adição de recursos requer que o build seja executado no Windows (excluindo Nano Server).</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: В файле конфигурации приложения должен присутствовать корневой элемент конфигурации.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: исполняемый файл узла приложения не будет настроен, так как для добавления ресурсов требуется, чтобы сборка выполнялась в Windows (за исключением Nano Server).</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.tr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: Uygulama yapılandırma dosyasının kök yapılandırma öğesi olmalıdır.</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: Kaynak eklemek derleme işleminin (Nano Server hariç) Windows'da gerçekleştirilmesini gerektirdiğinden uygulama konağının yürütülebilir dosyası özelleştirilmeyecek.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: 应用程序配置文件必须具有根配置元素。</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: 未自定义应用程序主机可执行文件,因为添加资源要求在 Windows (不包括 Nano 服务器)上执行生成。</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<target state="translated">NETSDK1070: 應用程式組態檔必須有根組態元素。</target>
<note>{StrBegin="NETSDK1070: "}</note>
</trans-unit>
<trans-unit id="AppHostCreationFailedWithRetry">
<source>NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</source>
<target state="new">NETSDK1113: Failed to create apphost (attempt {0} out of {1}): {2}</target>
<note>{StrBegin="NETSDK1113: "}</note>
</trans-unit>
<trans-unit id="AppHostCustomizationRequiresWindowsHostWarning">
<source>NETSDK1074: The application host executable will not be customized because adding resources requires that the build be performed on Windows (excluding Nano Server).</source>
<target state="translated">NETSDK1074: 因為正在新增需要在 Windows (不含 Nano 伺服器) 上執行組建的資源,所以該應用程式主機可執行檔無法進行自訂。</target>
Expand Down
70 changes: 53 additions & 17 deletions src/Tasks/Microsoft.NET.Build.Tasks/CreateAppHost.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.IO;
using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.NET.HostModel;
using Microsoft.NET.HostModel.AppHost;
using System;

namespace Microsoft.NET.Build.Tasks
{
Expand All @@ -14,6 +16,11 @@ namespace Microsoft.NET.Build.Tasks
/// </summary>
public class CreateAppHost : TaskBase
{
/// <summary>
/// The default delay, in milliseconds, for each retry attempt for creating the apphost.
/// </summary>
public const int DefaultRetryDelayMilliseconds = 1000;

[Required]
public string AppHostSourcePath { get; set; }

Expand All @@ -28,34 +35,63 @@ public class CreateAppHost : TaskBase

public bool WindowsGraphicalUserInterface { get; set; }

public int Retries { get; set; }

public int RetryDelayMilliseconds { get; set; } = DefaultRetryDelayMilliseconds;

protected override void ExecuteCore()
{
try
{
if (ResourceUpdater.IsSupportedOS())
var isGUI = WindowsGraphicalUserInterface;
var resourcesAssembly = IntermediateAssembly;

if (!ResourceUpdater.IsSupportedOS())
{
HostWriter.CreateAppHost(appHostSourceFilePath: AppHostSourcePath,
appHostDestinationFilePath: AppHostDestinationPath,
appBinaryFilePath: AppBinaryName,
windowsGraphicalUserInterface: WindowsGraphicalUserInterface,
assemblyToCopyResorcesFrom: IntermediateAssembly);
if (isGUI)
{
Log.LogWarning(Strings.AppHostCustomizationRequiresWindowsHostWarning);
}

isGUI = false;
resourcesAssembly = null;
}
else

int attempts = 0;

do
{
// by passing null to assemblyToCopyResorcesFrom, it will skip copying resorces,
// which is only supported on Windows
if (WindowsGraphicalUserInterface)
try
{
Log.LogWarning(Strings.AppHostCustomizationRequiresWindowsHostWarning);
HostWriter.CreateAppHost(appHostSourceFilePath: AppHostSourcePath,
appHostDestinationFilePath: AppHostDestinationPath,
appBinaryFilePath: AppBinaryName,
windowsGraphicalUserInterface: isGUI,
assemblyToCopyResorcesFrom: resourcesAssembly);
return;
}
catch (Exception ex) when (ex is IOException ||
ex is UnauthorizedAccessException)
//ex is ResourceUpdater.HResultException)
{
++attempts;

if (Retries < 0 || attempts == Retries) {
throw;
}

HostWriter.CreateAppHost(appHostSourceFilePath: AppHostSourcePath,
appHostDestinationFilePath: AppHostDestinationPath,
appBinaryFilePath: AppBinaryName,
windowsGraphicalUserInterface: false,
assemblyToCopyResorcesFrom: null);
Log.LogWarning(
string.Format(Strings.AppHostCreationFailedWithRetry,
attempts,
Retries,
ex.Message));

if (RetryDelayMilliseconds > 0) {
Thread.Sleep(RetryDelayMilliseconds);
}
}
}
while (attempts < Retries);
}
catch (AppNameTooLongException ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,12 +355,18 @@ Copyright (c) .NET Foundation. All rights reserved.
Exists('$(AppHostSourcePath)')">
<PropertyGroup>
<_UseWindowsGraphicalUserInterface Condition="($(RuntimeIdentifier.StartsWith('win')) or $(DefaultAppHostRuntimeIdentifier.StartsWith('win'))) and '$(OutputType)'=='WinExe'">true</_UseWindowsGraphicalUserInterface>
<CreateAppHostRetries Condition="'$(CreateAppHostRetries)' == ''">3</CreateAppHostRetries>
<CreateAppHostRetryDelay Condition="'$(CreateAppHostRetryDelay)' == ''">1000</CreateAppHostRetryDelay>
</PropertyGroup>

<CreateAppHost AppHostSourcePath="$(AppHostSourcePath)"
AppHostDestinationPath="$(AppHostIntermediatePath)"
AppBinaryName="$(AssemblyName)$(TargetExt)"
IntermediateAssembly="@(IntermediateAssembly->'%(FullPath)')"
WindowsGraphicalUserInterface="$(_UseWindowsGraphicalUserInterface)" />
WindowsGraphicalUserInterface="$(_UseWindowsGraphicalUserInterface)"
Retries="$(CreateAppHostRetries)"
RetryDelayMilliseconds="$(CreateAppHostRetryDelay)"
/>
</Target>

<!--
Expand Down
Loading

0 comments on commit 82e4029

Please sign in to comment.