Skip to content

Commit

Permalink
[wasm] Misc debugger improvements (#68988)
Browse files Browse the repository at this point in the history
* [wasm] Move the browser provisioning stuff to a new targets file

.. from `DebuggerTestSuite.csproj`. This will allow other projects to
use this too.

* [wasm][debugger] Handle failure to connect to the browser

* [wasm] Improve the browser path lookup

so it can be used outside the debugger tests project too. For example,
with Wasm.Build.Tests+playwright .

* [wasm][debugger] Throw exceptions from tasks correctly

.. using `ExceptionDispatchInfo.Capture` so we get the original stack
trace.

* [wasm][debugger] General improvements in debug proxy

- like logging
- updated API to make it easier to use by other projects, like the
  upcoming wasm-app-host .

* [wasm][debugger] Add support for setting an automatic breakpoint

.. on the first line of the entrypoint method (`Main`). This will be
useful for debugging with the upcoming wasm-app-host, along with the use
of `wait-for-debugger`.

Implemented by @thaystg .

* [wasm][debugger] Add support for wait_for_debugger

If requested, then it will cause invocation of `main` to be delayed till
a debugger is attached.

Implemented by @thaystg

* [wasm] Cleanup in Wasm.Build.Tests

.. in the lead up to wasm-app-host tests.

* [wasm] Update the default paths used to trigger builds on CI

.. to include templates, and provisioning props.

* disable non-wasm builds

* [wasm][debugger] Fix path to artifacts dir

* [wasm] Emit message with bundle path

* [wasm][templates] Make the project use the target dir's name as the

.. project name, instead of always creating `browser.dll`, and
`console.dll`.

* [wasm][debugger] Use a single static instance of HttpClient

.. as recommended by the documentation.

* Revert "disable non-wasm builds"

This reverts commit 7b8b60d.

* Address review feedback, and improve the autogenerated bpid
  • Loading branch information
radical committed May 13, 2022
1 parent 4751154 commit c26475c
Show file tree
Hide file tree
Showing 45 changed files with 566 additions and 302 deletions.
5 changes: 4 additions & 1 deletion eng/pipelines/common/evaluate-default-paths.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ jobs:
- src/tests/BuildWasmApps/*
- src/mono/wasm/build/*
- src/mono/wasm/runtime/*
- src/mono/wasm/templates/*
- src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/*
- src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/*
- src/mono/nuget/Microsoft.NET.Runtime.wasm.Sample.Mono/*
Expand All @@ -125,7 +126,9 @@ jobs:
include:
- src/mono/wasm/debugger/*
- src/mono/wasm/runtime/*
- src/mono/wasm/BrowsersForTesting.props
- src/tests/BuildWasmApps/*
- eng/testing/ProvisioningVersions.props
- eng/testing/scenarios/WasmDebuggerTestsJobsList.txt
- src/mono/mono/*
- subset: allwasm
include:
Expand Down
File renamed without changes.
67 changes: 67 additions & 0 deletions eng/testing/provisioning.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<Project>
<PropertyGroup>
<ChromeDir>$(ArtifactsBinDir)chrome\</ChromeDir>
<BrowserStampDir>$(ArtifactsBinDir)\</BrowserStampDir>
<ChromeStampFile>$(BrowserStampDir).install-chrome-$(ChromiumRevision).stamp</ChromeStampFile>
<FirefoxDir>$(ArtifactsBinDir)firefox\</FirefoxDir>
<FirefoxStampFile>$(BrowserStampDir).install-firefox-$(FirefoxRevision).stamp</FirefoxStampFile>
</PropertyGroup>

<Import Project="$(MSBuildThisFileDirectory)ProvisioningVersions.props" />

<Target Name="DownloadAndInstallChrome"
AfterTargets="Build"
Condition="!Exists($(ChromeStampFile)) and '$(InstallChromeForTests)' == 'true'">

<ItemGroup>
<_StampFile Include="$(BrowserStampDir).install-chrome*.stamp" />
</ItemGroup>

<Delete Files="@(_StampFile)" />
<RemoveDir Directories="$(ChromeDir)" />

<DownloadFile SourceUrl="$(ChromiumUrl)" DestinationFolder="$(ChromeDir)" SkipUnchangedFiles="true">
<Output TaskParameter="DownloadedFile" PropertyName="_DownloadedFile" />
</DownloadFile>
<Unzip SourceFiles="$(_DownloadedFile)" DestinationFolder="$(ChromeDir)" />

<PropertyGroup>
<_ChromeBinaryPath>$([MSBuild]::NormalizePath($(ChromeDir), $(ChromiumDirName), $(ChromiumBinaryName)))</_ChromeBinaryPath>
</PropertyGroup>

<Error Text="Cannot find chrome at $(_ChromeBinaryPath) in the downloaded copy"
Condition="!Exists($(_ChromeBinaryPath))" />

<Exec Command="chmod +x $(_ChromeBinaryPath)" Condition="!$([MSBuild]::IsOSPlatform('windows'))" />

<Touch Files="$(ChromeStampFile)" AlwaysCreate="true" />
</Target>

<Target Name="DownloadAndInstallFirefox"
AfterTargets="Build"
Condition="!Exists($(FirefoxStampFile)) and '$(InstallFirefoxForTests)' == 'true' and !$([MSBuild]::IsOSPlatform('windows'))">
<ItemGroup>
<_StampFile Include="$(BrowserStampDir).install-firefox*.stamp" />
</ItemGroup>

<Delete Files="@(_StampFile)" />
<RemoveDir Directories="$(FirefoxDir)" />

<DownloadFile SourceUrl="$(FirefoxUrl)" DestinationFolder="$(FirefoxDir)" SkipUnchangedFiles="true">
<Output TaskParameter="DownloadedFile" PropertyName="_DownloadedFile" />
</DownloadFile>
<Exec Command="tar -xf $(_DownloadedFile) -C $(FirefoxDir)"/>
<Exec Command="rm -rf $(_DownloadedFile)"/>

<PropertyGroup>
<_FirefoxBinaryPath>$([MSBuild]::NormalizePath($(FirefoxDir), $(FirefoxBinaryName)))</_FirefoxBinaryPath>
</PropertyGroup>

<Error Text="Cannot find firefox at $(_FirefoxBinaryPath) in the downloaded copy"
Condition="!Exists($(_FirefoxBinaryPath))" />

<Exec Command="chmod +x $(_FirefoxBinaryPath)"/>

<Touch Files="$(FirefoxStampFile)" AlwaysCreate="true" />
</Target>
</Project>
2 changes: 1 addition & 1 deletion src/libraries/sendtohelix-wasm.targets
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
</When>
</Choose>

<Import Project="$(RepoRoot)src\mono\wasm\BrowsersForTesting.props" />
<Import Project="$(RepositoryEngineeringDir)testing\ProvisioningVersions.props" />

<Target Name="PrepareForBuildHelixWorkItems_Wasm">
<PropertyGroup>
Expand Down
1 change: 1 addition & 0 deletions src/mono/wasm/build/WasmApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@
</WasmAppBuilder>

<CallTarget Targets="_GenerateRunV8Script" Condition="'$(WasmGenerateRunV8Script)' == 'true'" />
<Message Text="Generated app bundle at $(WasmAppDir)" Importance="High" />

<WriteLinesToFile File="$(WasmAppDir)\.stamp" Lines="" Overwrite="true" />
</Target>
Expand Down
65 changes: 65 additions & 0 deletions src/mono/wasm/debugger/BrowserDebugHost/DebugProxyHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

#nullable enable

namespace Microsoft.WebAssembly.Diagnostics;

public static class DebugProxyHost
{
public static Task RunDebugProxyAsync(ProxyOptions options, string[] args, ILoggerFactory loggerFactory, CancellationToken token)
{
return Task.WhenAny(
RunFirefoxServerLoopAsync(options, args, loggerFactory, token),
RunDevToolsProxyAsync(options, args, loggerFactory, token)
)
.ContinueWith(t => Console.WriteLine($"Debug proxy server failed with {t.Exception}"),
token,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.Default);
}

public static Task RunFirefoxServerLoopAsync(ProxyOptions options, string[] args, ILoggerFactory loggerFactory, CancellationToken token)
=> FirefoxDebuggerProxy.RunServerLoopAsync(browserPort: options.FirefoxDebugPort,
proxyPort: options.FirefoxProxyPort,
loggerFactory,
loggerFactory.CreateLogger("FirefoxMonoProxy"),
token,
autoSetBreakpointOnEntryPoint: options.AutoSetBreakpointOnEntryPoint);

public static async Task RunDevToolsProxyAsync(ProxyOptions options, string[] args, ILoggerFactory loggerFactory, CancellationToken token)
{
string proxyUrl = $"http://127.0.0.1:{options.DevToolsProxyPort}";
IWebHost host = new WebHostBuilder()
.UseSetting("UseIISIntegration", false.ToString())
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.ConfigureServices(services =>
{
services.AddSingleton(loggerFactory);
services.AddLogging(configure => configure.AddSimpleConsole().AddFilter(null, LogLevel.Information));
services.AddSingleton(Options.Create(options));
services.AddRouting();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddCommandLine(args);
})
.UseUrls(proxyUrl)
.Build();

token.Register(async () => { Console.WriteLine($"-- token got cancelled, stopping host"); await host.StopAsync(); });
await host.RunAsync(token);
}
}
57 changes: 21 additions & 36 deletions src/mono/wasm/debugger/BrowserDebugHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,53 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

#nullable enable

namespace Microsoft.WebAssembly.Diagnostics
{
public class ProxyOptions
{
public Uri DevToolsUrl { get; set; } = new Uri("http://localhost:9222");

public int? OwnerPid { get; set; }
}

public class Program
{
public static void Main(string[] args)
public static async Task Main(string[] args)
{
IConfigurationRoot config = new ConfigurationBuilder().AddCommandLine(args).Build();
int proxyPort = 0;
if (config["proxy-port"] is not null && int.TryParse(config["proxy-port"], out int port))
proxyPort = port;
int firefoxDebugPort = 6000;
if (config["firefox-debug-port"] is not null && int.TryParse(config["firefox-debug-port"], out int ffport))
firefoxDebugPort = ffport;
string? logPath = config["log-path"];

ProxyOptions options = new();
config.Bind(options);

using ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddSimpleConsole(options =>
{
options.TimestampFormat = "[HH:mm:ss] ";
})
.AddFilter(null, LogLevel.Debug);
.AddFilter("DevToolsProxy", LogLevel.Information)
.AddFilter("FirefoxMonoProxy", LogLevel.Information)
.AddFilter(null, LogLevel.Warning);
if (!string.IsNullOrEmpty(logPath))
builder.AddFile(Path.Combine(logPath, "proxy.log"),
if (!string.IsNullOrEmpty(options.LogPath))
builder.AddFile(Path.Combine(options.LogPath, "proxy.log"),
minimumLevel: LogLevel.Trace,
outputTemplate: "{Timestamp:o} [{Level:u3}] {SourceContext}: {Message}{NewLine}{Exception}");
});

ILogger logger = loggerFactory.CreateLogger("FirefoxMonoProxy");
_ = FirefoxDebuggerProxy.Run(browserPort: firefoxDebugPort, proxyPort: proxyPort, loggerFactory, logger);
CancellationTokenSource cts = new();
_ = Task.Run(() => DebugProxyHost.RunDebugProxyAsync(options, args, loggerFactory, cts.Token))
.ConfigureAwait(false);

IWebHost host = new WebHostBuilder()
.UseSetting("UseIISIntegration", false.ToString())
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddCommandLine(args);
})
.UseUrls($"http://127.0.0.1:{proxyPort}")
.Build();
TaskCompletionSource tcs = new();
Console.CancelKeyPress += (_, _) =>
{
tcs.SetResult();
cts.Cancel();
};

host.Run();
await tcs.Task;
}
}
}
31 changes: 31 additions & 0 deletions src/mono/wasm/debugger/BrowserDebugHost/ProxyOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

#nullable enable

namespace Microsoft.WebAssembly.Diagnostics;

public class ProxyOptions
{
public Uri DevToolsUrl { get; set; } = new Uri($"http://localhost:9222");
public int? OwnerPid { get; set; }
public int FirefoxProxyPort { get; set; } = 6300;
public int FirefoxDebugPort { get; set; } = 6000;
public int DevToolsProxyPort { get; set; } = 9300;
public int DevToolsDebugPort
{
get => DevToolsUrl.Port;
set
{
var builder = new UriBuilder(DevToolsUrl)
{
Port = value
};
DevToolsUrl = builder.Uri;
}
}
public string? LogPath { get; set; }
public bool AutoSetBreakpointOnEntryPoint { get; set; }
}
Loading

0 comments on commit c26475c

Please sign in to comment.