[msbuild] Delete any Mono crash dump files in the root app bundle before codesigning. Fixes #12320. (#12332)

This is what happens:

1. Mono will write crash dumps in the current directory:
   57bfe47451/src/mono/mono/utils/mono-state.c (L302-L322)
2. The current directory is by default the root of the app bundle.
3. If there are any files in the root of the app bundle for macOS or Mac
   Catalyst, 'codesign' will fail ("unsealed contents present in the bundle
   root").

This leads to the following sequence of events:

1. App developer builds & runs a Mac Catalyst app.
2. The app crashes for some reason.
3. Mono creates a crash dump (in the root directory of the app bundle).
4. The app developer changes something in the project and tries again.
5. The build fails, because 'codesign' fails.

Avoid this by deleting any crash dump files from the root of the app bundle
before signing the app.
This commit is contained in:
Rolf Bjarne Kvinge 2021-08-10 07:39:00 +02:00 коммит произвёл GitHub
Родитель 7dc6c9cffd
Коммит 15ace257ab
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 127 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Xamarin.MacDev.Tasks
{
public abstract class GetFileSystemEntriesTaskBase : XamarinTask
{
#region Inputs
[Required]
public string DirectoryPath { get; set; }
[Required]
public string Pattern { get; set; }
[Required]
public bool Recursive { get; set; }
#endregion
#region Outputs
[Output]
public ITaskItem[] Entries { get; set; }
#endregion
public override bool Execute ()
{
var searchOption = Recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
var entriesFullPath = Directory.GetFileSystemEntries (DirectoryPath, Pattern, searchOption);
Entries = entriesFullPath.Select (v => new TaskItem (v)).ToArray ();
return !Log.HasLoggedErrors;
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using Microsoft.Build.Framework;
using Xamarin.Messaging.Build.Client;
namespace Xamarin.MacDev.Tasks
{
public class GetFileSystemEntries : GetFileSystemEntriesTaskBase, ICancelableTask
{
public override bool Execute ()
{
if (ShouldExecuteRemotely ())
return new TaskRunner (SessionId, BuildEngine4).RunAsync (this).Result;
return base.Execute ();
}
public void Cancel ()
{
if (ShouldExecuteRemotely ())
BuildConnection.CancelAsync (SessionId, BuildEngine4).Wait ();
}
}
}

Просмотреть файл

@ -111,6 +111,7 @@ Copyright (C) 2018 Microsoft. All rights reserved.
<UsingTask TaskName="Xamarin.MacDev.Tasks.FindItemWithLogicalName" AssemblyFile="$(_TaskAssemblyName)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.GenerateBundleName" AssemblyFile="$(_TaskAssemblyName)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.GetDirectories" AssemblyFile="$(_TaskAssemblyName)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.GetFileSystemEntries" AssemblyFile="$(_TaskAssemblyName)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.GetFullPath" AssemblyFile="$(_TaskAssemblyName)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.GetMinimumOSVersion" AssemblyFile="$(_TaskAssemblyName)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.GetNativeExecutableName" AssemblyFile="$(_TaskAssemblyName)" />

Просмотреть файл

@ -778,6 +778,23 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved.
<_CodesignDisableTimestamp Condition="'$(_SdkIsSimulator)' == 'true' Or '$(_BundlerDebug)' == 'true'">True</_CodesignDisableTimestamp>
</PropertyGroup>
<!-- Delete any crash dumps in the app bundle that might exist. Ref: https://github.com/xamarin/xamarin-macios/issues/12320 -->
<!-- Use a task to collect the files, so that we get the correct behavior on Windows -->
<GetFileSystemEntries
SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true'"
DirectoryPath="$(AppBundleDir)"
Pattern="mono_crash.mem.*"
Recursive="false"
>
<Output TaskParameter="Entries" ItemName="_MonoCrashDumpsInAppBundle" />
</GetFileSystemEntries>
<Delete
SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true'"
Files="@(_MonoCrashDumpsInAppBundle)"
/>
<Codesign
SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true'"

Просмотреть файл

@ -529,6 +529,30 @@ namespace Xamarin.Tests {
Assert.AreEqual ($"The RuntimeIdentifier '{runtimeIdentifier}' is invalid.", errors [0].Message, "Error message");
}
[Test]
[TestCase (ApplePlatform.MacCatalyst, "maccatalyst-x64")]
public void FilesInAppBundle (ApplePlatform platform, string runtimeIdentifiers)
{
var project = "MySimpleApp";
Configuration.IgnoreIfIgnoredPlatform (platform);
var project_path = GetProjectPath (project, runtimeIdentifiers: runtimeIdentifiers, platform: platform, out var appPath);
Clean (project_path);
var properties = new Dictionary<string, string> (verbosity);
SetRuntimeIdentifiers (properties, runtimeIdentifiers);
// Build
DotNet.AssertBuild (project_path, properties);
// Simulate a crash dump
var crashDump = Path.Combine (appPath, "mono_crash.mem.123456.something.blob");
File.WriteAllText (crashDump, "A crash dump");
// Build again
DotNet.AssertBuild (project_path, properties);
}
[Test]
[TestCase (ApplePlatform.MacOSX, "osx-x64")]
[TestCase (ApplePlatform.MacOSX, "osx-arm64")]

Просмотреть файл

@ -11,6 +11,7 @@ using NUnit.Framework;
using Xamarin.Utils;
using Xamarin.Tests;
using Xamarin.MacDev;
using Xamarin.Utils;
namespace Xamarin.Tests {
[TestFixture]
@ -20,6 +21,25 @@ namespace Xamarin.Tests {
{ "MonoBundlingExtraArgs", "-v" },
};
protected void SetRuntimeIdentifiers (Dictionary<string, string> properties, string runtimeIdentifiers)
{
var multiRid = runtimeIdentifiers.IndexOf (';') >= 0 ? "RuntimeIdentifiers" : "RuntimeIdentifier";
properties [multiRid] = runtimeIdentifiers;
}
protected string GetProjectPath (string project, string runtimeIdentifiers, ApplePlatform platform, out string appPath, string subdir = null)
{
return GetProjectPath (project, null, runtimeIdentifiers, platform, out appPath);
}
protected string GetProjectPath (string project, string subdir, string runtimeIdentifiers, ApplePlatform platform, out string appPath)
{
var rv = GetProjectPath (project, subdir, platform);
var appPathRuntimeIdentifier = runtimeIdentifiers.IndexOf (';') >= 0 ? "" : runtimeIdentifiers;
appPath = Path.Combine (Path.GetDirectoryName (rv), "bin", "Debug", platform.ToFramework (), appPathRuntimeIdentifier, project + ".app");
return rv;
}
protected string GetProjectPath (string project, string subdir = null, ApplePlatform? platform = null)
{
var project_dir = Path.Combine (Configuration.SourceRoot, "tests", "dotnet", project);