diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml index e6be56a9307d60..0efe765230720f 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml @@ -119,7 +119,7 @@ jobs: alwaysRun: ${{ parameters.isWasmOnlyBuild }} # NOTE - Since threading is experimental, we don't want to block mainline work - shouldContinueOnError: true + # TODO put back shouldContinueOnError: true scenarios: - WasmTestOnBrowser #- WasmTestOnNodeJS - this is not supported yet, https://github.com/dotnet/runtime/issues/85592 diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs index 573006673d8889..6da081c4e86ab0 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleFormatterTests.cs @@ -74,7 +74,6 @@ internal static (ConsoleLogger Logger, ConsoleSink Sink, ConsoleSink ErrorSink, } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_TimeStampFormat_IsReloaded() { // Arrange @@ -88,7 +87,6 @@ public void ConsoleLoggerOptions_TimeStampFormat_IsReloaded() } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatterNames))] public void InvalidLogLevel_Throws(string formatterName) { @@ -103,7 +101,6 @@ public void InvalidLogLevel_Throws(string formatterName) } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatterNamesAndLevels))] public void NoMessageOrException_Noop(string formatterName, LogLevel level) { @@ -123,7 +120,6 @@ public void NoMessageOrException_Noop(string formatterName, LogLevel level) } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatterNamesAndLevels))] public void Log_LogsCorrectTimestamp(string formatterName, LogLevel level) { diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs index f0ef3d6cd7e1d1..0994980590122b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs @@ -174,7 +174,6 @@ internal static string GetJsonLogLevelString(LogLevel logLevel) } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void LogsWhenMessageIsNotProvided() { // Arrange @@ -207,7 +206,6 @@ public void LogsWhenMessageIsNotProvided() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void DoesNotLog_NewLine_WhenNoExceptionIsProvided() { // Arrange @@ -236,7 +234,6 @@ public void DoesNotLog_NewLine_WhenNoExceptionIsProvided() } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [InlineData(null, 0)] [InlineData(null, 1)] [InlineData("missingFormatter", 0)] @@ -279,7 +276,6 @@ public void Options_FormatterNameNull_UsesDeprecatedProperties(string formatterN } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [InlineData("Route with name 'Simple' was not found.")] public void Writes_NewLine_WhenExceptionIsProvided(string message) { @@ -304,7 +300,6 @@ public void Writes_NewLine_WhenExceptionIsProvided(string message) } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ThrowsException_WhenNoFormatterIsProvided() { // Arrange @@ -316,7 +311,6 @@ public void ThrowsException_WhenNoFormatterIsProvided() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void LogsWhenNullFilterGiven() { // Arrange @@ -338,7 +332,6 @@ public void LogsWhenNullFilterGiven() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void WriteCritical_LogsCorrectColors() { // Arrange @@ -360,7 +353,6 @@ public void WriteCritical_LogsCorrectColors() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void WriteError_LogsCorrectColors() { // Arrange @@ -382,7 +374,6 @@ public void WriteError_LogsCorrectColors() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void WriteWarning_LogsCorrectColors() { // Arrange @@ -404,7 +395,6 @@ public void WriteWarning_LogsCorrectColors() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void WriteInformation_LogsCorrectColors() { // Arrange @@ -456,7 +446,6 @@ public void AddConsole_IsOutputRedirected_ColorDisabled() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void WriteDebug_LogsCorrectColors() { // Arrange @@ -478,7 +467,6 @@ public void WriteDebug_LogsCorrectColors() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void WriteTrace_LogsCorrectColors() { // Arrange @@ -500,7 +488,6 @@ public void WriteTrace_LogsCorrectColors() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void WriteAllLevelsDisabledColors_LogsNoColors() { // Arrange @@ -525,7 +512,6 @@ public void WriteAllLevelsDisabledColors_LogsNoColors() } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatsAndLevels))] public void Log_LogsCorrectTimestamp(ConsoleLoggerFormat format, LogLevel level) { @@ -567,7 +553,6 @@ public void Log_LogsCorrectTimestamp(ConsoleLoggerFormat format, LogLevel level) } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatsAndLevels))] public void WriteCore_LogsCorrectTimestampInUtc(ConsoleLoggerFormat format, LogLevel level) { @@ -609,7 +594,6 @@ public void WriteCore_LogsCorrectTimestampInUtc(ConsoleLoggerFormat format, LogL } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatsAndLevels))] public void WriteCore_LogsCorrectMessages(ConsoleLoggerFormat format, LogLevel level) { @@ -654,7 +638,6 @@ public void WriteCore_LogsCorrectMessages(ConsoleLoggerFormat format, LogLevel l } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void NoLogScope_DoesNotWriteAnyScopeContentToOutput() { // Arrange @@ -676,7 +659,6 @@ public void NoLogScope_DoesNotWriteAnyScopeContentToOutput() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void WritingScopes_LogsWithCorrectColors() { // Arrange @@ -703,7 +685,6 @@ public void WritingScopes_LogsWithCorrectColors() } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(Formats))] public void WritingScopes_LogsExpectedMessage(ConsoleLoggerFormat format) { @@ -755,7 +736,6 @@ public void WritingScopes_LogsExpectedMessage(ConsoleLoggerFormat format) } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(Formats))] public void WritingNestedScope_LogsNullScopeName(ConsoleLoggerFormat format) { @@ -805,7 +785,6 @@ public void WritingNestedScope_LogsNullScopeName(ConsoleLoggerFormat format) } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(Formats))] public void WritingNestedScopes_LogsExpectedMessage(ConsoleLoggerFormat format) { @@ -864,7 +843,6 @@ public void WritingNestedScopes_LogsExpectedMessage(ConsoleLoggerFormat format) } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(Formats))] public void WritingMultipleScopes_LogsExpectedMessage(ConsoleLoggerFormat format) { @@ -934,7 +912,6 @@ public void WritingMultipleScopes_LogsExpectedMessage(ConsoleLoggerFormat format } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void CallingBeginScopeOnLogger_AlwaysReturnsNewDisposableInstance() { // Arrange @@ -953,7 +930,6 @@ public void CallingBeginScopeOnLogger_AlwaysReturnsNewDisposableInstance() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void CallingBeginScopeOnLogger_ReturnsNonNullableInstance() { // Arrange @@ -969,7 +945,6 @@ public void CallingBeginScopeOnLogger_ReturnsNonNullableInstance() } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(Formats))] public void ConsoleLoggerLogsToError_WhenOverErrorLevel(ConsoleLoggerFormat format) { @@ -1020,7 +995,6 @@ public void ConsoleLoggerLogsToError_WhenOverErrorLevel(ConsoleLoggerFormat form } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatsAndLevels))] public void WriteCore_NullMessageWithException(ConsoleLoggerFormat format, LogLevel level) { @@ -1065,7 +1039,6 @@ public void WriteCore_NullMessageWithException(ConsoleLoggerFormat format, LogLe } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatsAndLevels))] public void WriteCore_EmptyMessageWithException(ConsoleLoggerFormat format, LogLevel level) { @@ -1109,7 +1082,6 @@ public void WriteCore_EmptyMessageWithException(ConsoleLoggerFormat format, LogL } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(FormatsAndLevels))] public void WriteCore_MessageWithNullException(ConsoleLoggerFormat format, LogLevel level) { @@ -1150,7 +1122,6 @@ public void WriteCore_MessageWithNullException(ConsoleLoggerFormat format, LogLe } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [MemberData(nameof(Levels))] public void WriteCore_NullMessageWithNullException(LogLevel level) { @@ -1169,7 +1140,6 @@ public void WriteCore_NullMessageWithNullException(LogLevel level) } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void IsEnabledReturnsCorrectValue() { var logger = SetUp().Logger; @@ -1184,7 +1154,6 @@ public static void IsEnabledReturnsCorrectValue() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_DisableColors_IsAppliedToLoggers() { // Arrange @@ -1219,7 +1188,6 @@ public void ConsoleLoggerOptions_SetInvalidBufferMode_Throws() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_DisableColors_IsReadFromLoggingConfiguration() { var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:DisableColors", "true") }).Build(); @@ -1237,7 +1205,6 @@ public void ConsoleLoggerOptions_DisableColors_IsReadFromLoggingConfiguration() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_TimeStampFormat_IsReloaded() { // Arrange @@ -1252,7 +1219,6 @@ public void ConsoleLoggerOptions_TimeStampFormat_IsReloaded() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_TimeStampFormat_IsReadFromLoggingConfiguration() { var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:TimeStampFormat", "yyyyMMddHHmmss") }).Build(); @@ -1270,7 +1236,6 @@ public void ConsoleLoggerOptions_TimeStampFormat_IsReadFromLoggingConfiguration( } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_TimeStampFormat_MultipleReloads() { var monitor = new TestOptionsMonitor(new ConsoleLoggerOptions()); @@ -1285,7 +1250,6 @@ public void ConsoleLoggerOptions_TimeStampFormat_MultipleReloads() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_IncludeScopes_IsAppliedToLoggers() { // Arrange @@ -1300,7 +1264,6 @@ public void ConsoleLoggerOptions_IncludeScopes_IsAppliedToLoggers() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_LogAsErrorLevel_IsReadFromLoggingConfiguration() { var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:LogToStandardErrorThreshold", "Warning") }).Build(); @@ -1318,7 +1281,6 @@ public void ConsoleLoggerOptions_LogAsErrorLevel_IsReadFromLoggingConfiguration( } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_LogAsErrorLevel_IsAppliedToLoggers() { // Arrange @@ -1333,7 +1295,6 @@ public void ConsoleLoggerOptions_LogAsErrorLevel_IsAppliedToLoggers() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_UpdateQueueOptions_UpdatesConsoleLoggerProcessorProperties() { // Arrange @@ -1353,7 +1314,6 @@ public void ConsoleLoggerOptions_UpdateQueueOptions_UpdatesConsoleLoggerProcesso } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_UseUtcTimestamp_IsAppliedToLoggers() { // Arrange @@ -1368,7 +1328,6 @@ public void ConsoleLoggerOptions_UseUtcTimestamp_IsAppliedToLoggers() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public void ConsoleLoggerOptions_IncludeScopes_IsReadFromLoggingConfiguration() { var configuration = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Console:IncludeScopes", "true") }).Build(); diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/DI.Common/Common/tests/Microsoft.Extensions.Logging.Testing.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging/tests/DI.Common/Common/tests/Microsoft.Extensions.Logging.Testing.Tests.csproj index 49e334b679eebb..7dc147ea8fe4b7 100644 --- a/src/libraries/Microsoft.Extensions.Logging/tests/DI.Common/Common/tests/Microsoft.Extensions.Logging.Testing.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Logging/tests/DI.Common/Common/tests/Microsoft.Extensions.Logging.Testing.Tests.csproj @@ -4,6 +4,10 @@ true + + --setenv=XHARNESS_LOG_TEST_START=true --no-memory-snapshot + + diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/System.Diagnostics.TraceSource.Config.Tests.csproj b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/System.Diagnostics.TraceSource.Config.Tests.csproj index cd36a59ecae62a..7a8bdffe6d237d 100644 --- a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/System.Diagnostics.TraceSource.Config.Tests.csproj +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Config.Tests/System.Diagnostics.TraceSource.Config.Tests.csproj @@ -3,6 +3,9 @@ true $(NetCoreAppCurrent) + + --setenv=XHARNESS_LOG_TEST_START=true --no-memory-snapshot + diff --git a/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs b/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs index 2913efbe3cdf6c..85070e1534a8ee 100644 --- a/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs @@ -294,7 +294,6 @@ public async Task WritesUsingGetMemoryWorks() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91547", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public async Task CompleteWithLargeWriteThrows() { var completeDelay = TimeSpan.FromMilliseconds(10); diff --git a/src/libraries/System.Linq.Parallel/tests/ExchangeTests.cs b/src/libraries/System.Linq.Parallel/tests/ExchangeTests.cs index 5c36f46c5d2073..6c99c02ccdfa5d 100644 --- a/src/libraries/System.Linq.Parallel/tests/ExchangeTests.cs +++ b/src/libraries/System.Linq.Parallel/tests/ExchangeTests.cs @@ -116,6 +116,7 @@ public static void Partitioning_Default_Longrunning(Labeled> [ConditionalTheory] [MemberData(nameof(PartitioningData), new[] { 0, 1, 2, 16, 1024 })] + [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void Partitioning_Striped(Labeled> labeled, int count, int partitions) { if (partitions > 1 && !PlatformDetection.IsThreadingSupported) diff --git a/src/libraries/System.Threading.Tasks.Parallel/tests/System.Threading.Tasks.Parallel.Tests.csproj b/src/libraries/System.Threading.Tasks.Parallel/tests/System.Threading.Tasks.Parallel.Tests.csproj index 4be608cc6847ac..7a599ea739d7cb 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/tests/System.Threading.Tasks.Parallel.Tests.csproj +++ b/src/libraries/System.Threading.Tasks.Parallel/tests/System.Threading.Tasks.Parallel.Tests.csproj @@ -6,6 +6,9 @@ + + --setenv=XHARNESS_LOG_TEST_START=true --no-memory-snapshot + diff --git a/src/libraries/System.Threading.Tasks/tests/System.Threading.Tasks.Tests.csproj b/src/libraries/System.Threading.Tasks/tests/System.Threading.Tasks.Tests.csproj index dfd17dfa6e6d45..c16ca8af166263 100644 --- a/src/libraries/System.Threading.Tasks/tests/System.Threading.Tasks.Tests.csproj +++ b/src/libraries/System.Threading.Tasks/tests/System.Threading.Tasks.Tests.csproj @@ -5,6 +5,9 @@ $(NetCoreAppCurrent) <_WasmPThreadPoolSize Condition="'$(MonoWasmBuildVariant)' == 'multithread'">64 + + --setenv=XHARNESS_LOG_TEST_START=true --no-memory-snapshot + diff --git a/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs b/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs index 4c2c5cc53a5249..4c0655795409d6 100644 --- a/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs +++ b/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs @@ -72,7 +72,6 @@ public static void RunSemaphoreSlimTest1_Wait_NegativeCases() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] public static void RunSemaphoreSlimTest1_WaitAsync() { // Infinite timeout @@ -464,7 +463,6 @@ private static void RunSemaphoreSlimTest7_AvailableWaitHandle_Helper(int initial /// The final semaphore count /// True if the test succeeded, false otherwise [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91538", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [InlineData(5, 1000, 50, 50, 50, 0, 5, 1000)] [InlineData(0, 1000, 50, 25, 25, 25, 0, 500)] [InlineData(0, 1000, 50, 0, 0, 50, 0, 100)] @@ -531,7 +529,6 @@ public static void RunSemaphoreSlimTest8_ConcWaitAndRelease(int initial, int max /// The final semaphore count /// True if the test succeeded, false otherwise [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/91541", typeof(PlatformDetection), nameof(PlatformDetection.IsWasmThreadingSupported))] [InlineData(5, 1000, 50, 50, 50, 0, 5, 500)] [InlineData(0, 1000, 50, 25, 25, 25, 0, 500)] [InlineData(0, 1000, 50, 0, 0, 50, 0, 100)] diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 88ac0d5f0aac1e..a1de1433304181 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -61,6 +61,14 @@ + + + + + + + + @@ -568,7 +576,9 @@ + diff --git a/src/mono/mono/component/diagnostics_server.c b/src/mono/mono/component/diagnostics_server.c index 4bea3d722625c5..e32499ea1e408a 100644 --- a/src/mono/mono/component/diagnostics_server.c +++ b/src/mono/mono/component/diagnostics_server.c @@ -250,7 +250,7 @@ queue_push_sync (WasmIpcStreamQueue *q, const uint8_t *buf, uint32_t buf_size, u gboolean is_browser_thread = FALSE; while (mono_atomic_load_i32 (&q->buf_full) != 0) { if (G_UNLIKELY (!is_browser_thread_inited)) { - is_browser_thread = mono_threads_wasm_is_ui_thread (); + is_browser_thread = mono_threads_wasm_is_deputy_thread (); is_browser_thread_inited = TRUE; } if (G_UNLIKELY (is_browser_thread)) { diff --git a/src/mono/mono/metadata/sgen-stw.c b/src/mono/mono/metadata/sgen-stw.c index daaafba2aef7c3..b27699434f3987 100644 --- a/src/mono/mono/metadata/sgen-stw.c +++ b/src/mono/mono/metadata/sgen-stw.c @@ -503,7 +503,8 @@ mono_wasm_gc_lock(void) MONO_ENTER_GC_UNSAFE; #ifndef DISABLE_THREADS /* only the browser thread is allowed to take the GC lock */ - g_assert (mono_threads_wasm_is_ui_thread ()); + // FIXME, to make it work for deputy + g_assert (mono_threads_wasm_is_deputy_thread ()); LOCK_GC; acquire_gc_locks(); #else diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c index dbed9f92e7f883..b177dc33a84295 100644 --- a/src/mono/mono/metadata/threads.c +++ b/src/mono/mono/metadata/threads.c @@ -99,8 +99,11 @@ mono_native_thread_join_handle (HANDLE thread_handle, gboolean close_handle); #include "icall-decl.h" -/*#define THREAD_DEBUG(a) do { a; } while (0)*/ +#ifdef DEBUG +#define THREAD_DEBUG(a) do { a; } while (0) +#else #define THREAD_DEBUG(a) +#endif // DEBUG /*#define THREAD_WAIT_DEBUG(a) do { a; } while (0)*/ #define THREAD_WAIT_DEBUG(a) /*#define LIBGC_DEBUG(a) do { a; } while (0)*/ diff --git a/src/mono/mono/utils/mono-threads-debug.h b/src/mono/mono/utils/mono-threads-debug.h index ded80a96f3ab1b..359b91626501b0 100644 --- a/src/mono/mono/utils/mono-threads-debug.h +++ b/src/mono/mono/utils/mono-threads-debug.h @@ -15,7 +15,7 @@ #define MOSTLY_ASYNC_SAFE_PRINTF(...) MOSTLY_ASYNC_SAFE_FPRINTF(1, __VA_ARGS__); -#if 1 +#ifndef DEBUG #define THREADS_DEBUG(...) #else #define THREADS_DEBUG MOSTLY_ASYNC_SAFE_PRINTF @@ -27,7 +27,7 @@ #define THREADS_STW_DEBUG MOSTLY_ASYNC_SAFE_PRINTF #endif -#if 1 +#ifndef DEBUG #define THREADS_SUSPEND_DEBUG(...) #else #define THREADS_SUSPEND_DEBUG MOSTLY_ASYNC_SAFE_PRINTF diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index b31faae8e1173f..3a1a3672237036 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -471,6 +471,30 @@ mono_threads_wasm_ui_thread_tid (void) #endif } +#ifndef DISABLE_THREADS +static pthread_t deputy_thread_tid; +#endif + +gboolean +mono_threads_wasm_is_deputy_thread (void) +{ +#ifdef DISABLE_THREADS + return TRUE; +#else + return pthread_self () == deputy_thread_tid; +#endif +} + +MonoNativeThreadId +mono_threads_wasm_deputy_thread_tid (void) +{ +#ifdef DISABLE_THREADS + return (MonoNativeThreadId)1; +#else + return (MonoNativeThreadId) deputy_thread_tid; +#endif +} + #ifndef DISABLE_THREADS extern void mono_wasm_pthread_on_pthread_attached (MonoNativeThreadId pthread_id); extern void mono_wasm_pthread_on_pthread_detached (MonoNativeThreadId pthread_id); @@ -549,6 +573,47 @@ mono_threads_wasm_async_run_in_target_thread_vii (pthread_t target_thread, void emscripten_dispatch_to_thread_async (target_thread, EM_FUNC_SIG_VII, func, NULL, user_data1, user_data2); } +extern void mono_wasm_setup_deputy_thread (void); + +// this is running in deputy thread +static void* +deputy_thread_fn (void* unused_arg G_GNUC_UNUSED) +{ + mono_wasm_setup_deputy_thread(); + + // "exit" from server_thread, but keep the pthread alive and responding to events + emscripten_exit_with_live_runtime (); +} + +EMSCRIPTEN_KEEPALIVE gboolean +mono_wasm_create_deputy_thread (pthread_t *out_thread_id) +{ + if (!pthread_create (&deputy_thread_tid, NULL, deputy_thread_fn, NULL)) { + *out_thread_id = deputy_thread_tid; + return TRUE; + } + memset(out_thread_id, 0, sizeof(pthread_t)); + return FALSE; +} + +void +mono_threads_wasm_async_run_in_deputy_thread (void (*func) (void)) +{ + mono_threads_wasm_async_run_in_target_thread (deputy_thread_tid, func); +} + +void +mono_threads_wasm_async_run_in_deputy_thread_vi (void (*func) (gpointer), gpointer user_data) +{ + mono_threads_wasm_async_run_in_target_thread_vi (deputy_thread_tid, func, user_data); +} + +void +mono_threads_wasm_async_run_in_deputy_thread_vii (void (*func) (gpointer, gpointer), gpointer user_data1, gpointer user_data2) +{ + mono_threads_wasm_async_run_in_target_thread_vii (deputy_thread_tid, func, user_data1, user_data2); +} + #endif /* DISABLE_THREADS */ diff --git a/src/mono/mono/utils/mono-threads-wasm.h b/src/mono/mono/utils/mono-threads-wasm.h index 157fc22af8859a..046f6aae9c5a3b 100644 --- a/src/mono/mono/utils/mono-threads-wasm.h +++ b/src/mono/mono/utils/mono-threads-wasm.h @@ -23,9 +23,15 @@ gboolean mono_threads_wasm_is_ui_thread (void); +gboolean +mono_threads_wasm_is_deputy_thread (void); + MonoNativeThreadId mono_threads_wasm_ui_thread_tid (void); +MonoNativeThreadId +mono_threads_wasm_deputy_thread_tid (void); + #ifndef DISABLE_THREADS /** * Runs the given function asynchronously on the main thread. @@ -52,6 +58,19 @@ mono_threads_wasm_async_run_in_target_thread_vi (pthread_t target_thread, void ( void mono_threads_wasm_async_run_in_target_thread_vii (pthread_t target_thread, void (*func) (gpointer, gpointer), gpointer user_data1, gpointer user_data2); +gboolean +mono_wasm_create_deputy_thread (pthread_t *out_thread_id); + +void +mono_threads_wasm_async_run_in_deputy_thread (void (*func) (void)); + +void +mono_threads_wasm_async_run_in_deputy_thread_vi (void (*func)(gpointer), gpointer user_data); + +void +mono_threads_wasm_async_run_in_deputy_thread_vii (void (*func)(gpointer, gpointer), gpointer user_data1, gpointer user_data2); + + static inline int32_t mono_wasm_atomic_wait_i32 (volatile int32_t *addr, int32_t expected, int32_t timeout_ns) diff --git a/src/mono/sample/wasm/browser-threads-minimal/Wasm.Browser.Threads.Minimal.Sample.csproj b/src/mono/sample/wasm/browser-threads-minimal/Wasm.Browser.Threads.Minimal.Sample.csproj index bd8644d2fefd30..ddcf9116e02213 100644 --- a/src/mono/sample/wasm/browser-threads-minimal/Wasm.Browser.Threads.Minimal.Sample.csproj +++ b/src/mono/sample/wasm/browser-threads-minimal/Wasm.Browser.Threads.Minimal.Sample.csproj @@ -1,6 +1,7 @@ true + multithread diff --git a/src/mono/sample/wasm/browser-threads-minimal/main.js b/src/mono/sample/wasm/browser-threads-minimal/main.js index 72631334586fb6..329a45aa99b429 100644 --- a/src/mono/sample/wasm/browser-threads-minimal/main.js +++ b/src/mono/sample/wasm/browser-threads-minimal/main.js @@ -12,9 +12,6 @@ try { const { getAssemblyExports, runMain } = await dotnet //.withEnvironmentVariable("MONO_LOG_LEVEL", "debug") //.withDiagnosticTracing(true) - .withConfig({ - pthreadPoolSize: 6, - }) .withElementOnExit() .withExitCodeLogging() .create(); diff --git a/src/mono/sample/wasm/browser/Program.cs b/src/mono/sample/wasm/browser/Program.cs index ce542da6201921..47b9c726349104 100644 --- a/src/mono/sample/wasm/browser/Program.cs +++ b/src/mono/sample/wasm/browser/Program.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Threading; +using System.Threading.Tasks; using System.Runtime.InteropServices.JavaScript; using System.Runtime.InteropServices; @@ -9,13 +11,46 @@ namespace Sample { public partial class Test { - public static int Main(string[] args) + public static async Task Main(string[] args) { - DisplayMeaning(42); + Console.WriteLine($"smoke: TestCanStartThread 0 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + var are = new AutoResetEvent(false); + /* + var t = new Thread(() => + { + Console.WriteLine($"smoke: TestCanStartThread 2 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + are.Set(); + Console.WriteLine($"smoke: TestCanStartThread 3 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + }); + */ + /* + var factory = new TaskFactory(); + await factory.StartNew(() => + { + Console.WriteLine($"smoke: TestCanStartThread 2 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + are.Set(); + Console.WriteLine($"smoke: TestCanStartThread 3 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + }, TaskCreationOptions.LongRunning); + */ + var p = Task.Run(async ()=>{ + Console.WriteLine($"smoke: TestCanStartThread 1 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + await Task.Delay(1000); + Console.WriteLine($"smoke: TestCanStartThread 2 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + are.Set(); + Console.WriteLine($"smoke: TestCanStartThread 3 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + }); + + Console.WriteLine($"smoke: TestCanStartThread 4 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + + are.WaitOne(); + + Console.WriteLine($"smoke: TestCanStartThread 5 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + + await p; + + Console.WriteLine($"smoke: TestCanStartThread 6 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}"); + return 0; } - - [JSImport("Sample.Test.displayMeaning", "main.js")] - internal static partial void DisplayMeaning(int meaning); } } diff --git a/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj b/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj index 365ba7276cb0b9..4f97a682fbb1b7 100644 --- a/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj +++ b/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj @@ -1,4 +1,8 @@ + + true + multithread + diff --git a/src/mono/sample/wasm/browser/main.js b/src/mono/sample/wasm/browser/main.js index ba84cca682189b..a199f107319dd4 100644 --- a/src/mono/sample/wasm/browser/main.js +++ b/src/mono/sample/wasm/browser/main.js @@ -3,23 +3,15 @@ import { dotnet, exit } from './_framework/dotnet.js' -function displayMeaning(meaning) { - document.getElementById("out").innerHTML = `${meaning}`; -} +setInterval(() => { + console.log("UI thread is alive!"); +}, 1000); try { - const { setModuleImports } = await dotnet + await dotnet .withElementOnExit() .create(); - setModuleImports("main.js", { - Sample: { - Test: { - displayMeaning - } - } - }); - await dotnet.run(); } catch (err) { diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs index c28f18a3c57469..9f7acf6a6ea666 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs @@ -12,7 +12,7 @@ #nullable enable namespace Wasm.Build.Tests.MT.Blazor; - +/* until JS interop in deputy public class SimpleMultiThreadedTests : BlazorWasmTestBase { public SimpleMultiThreadedTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) @@ -76,3 +76,4 @@ await BlazorRunForPublishWithWebServer( throw new XunitException($"Errors found in browser console output:\n{errorOutput}"); } } +*/ diff --git a/src/mono/wasm/debugger/Wasm.Debugger.Tests/wasm.helix.targets b/src/mono/wasm/debugger/Wasm.Debugger.Tests/wasm.helix.targets index e645a2c42c4d5d..38adf24927ab05 100644 --- a/src/mono/wasm/debugger/Wasm.Debugger.Tests/wasm.helix.targets +++ b/src/mono/wasm/debugger/Wasm.Debugger.Tests/wasm.helix.targets @@ -12,19 +12,6 @@ - - - - - - - - $(TestArchiveTestsDir)Wasm.Debugger.Tests.zip - $(HelixCommand) - $(_DebuggerTestsWorkItemTimeout) - set "TEST_ARGS=--filter category^^!=failing^&FullyQualifiedName~%(Identity)" - export "TEST_ARGS=--filter category!=failing&FullyQualifiedName~%(Identity)" - - + diff --git a/src/mono/wasm/runtime/cwraps.ts b/src/mono/wasm/runtime/cwraps.ts index 4026be432c3004..f64a822648257f 100644 --- a/src/mono/wasm/runtime/cwraps.ts +++ b/src/mono/wasm/runtime/cwraps.ts @@ -41,6 +41,7 @@ const threading_cwraps: SigLine[] = MonoWasmThreads ? [ [true, "mono_wasm_diagnostic_server_thread_attach_to_runtime", "void", []], [true, "mono_wasm_diagnostic_server_post_resume_runtime", "void", []], [true, "mono_wasm_diagnostic_server_create_stream", "number", []], + [true, "mono_wasm_create_deputy_thread", "bool", ["number"]], ] : []; // when the method is assigned/cached at usage, instead of being invoked directly from cwraps, it can't be marked lazy, because it would be re-bound on each call @@ -181,6 +182,7 @@ export interface t_ThreadingCwraps { mono_wasm_diagnostic_server_thread_attach_to_runtime(): void; mono_wasm_diagnostic_server_post_resume_runtime(): void; mono_wasm_diagnostic_server_create_stream(): VoidPtr; + mono_wasm_create_deputy_thread(threadIdOutPtr: VoidPtr): boolean; } export interface t_ProfilerCwraps { diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c index b3bac44d0d6858..4d2c56c7562363 100644 --- a/src/mono/wasm/runtime/driver.c +++ b/src/mono/wasm/runtime/driver.c @@ -662,6 +662,20 @@ mono_wasm_invoke_method_bound (MonoMethod *method, void* args /*JSMarshalerArgum return is_err; } +#ifndef DISABLE_THREADS +// this is running in deputy thread +EMSCRIPTEN_KEEPALIVE void +mono_wasm_invoke_method_bound_deputy (MonoMethod *method, void* args /*JSMarshalerArguments*/) +{ + mono_wasm_invoke_method_bound(method, args, NULL); + free(args); +} + +void +mono_threads_wasm_async_run_in_deputy_thread_vii (void (*func)(gpointer, gpointer), gpointer user_data1, gpointer user_data2); + +#endif + EMSCRIPTEN_KEEPALIVE MonoMethod* mono_wasm_assembly_get_entry_point (MonoAssembly *assembly, int auto_insert_breakpoint) { @@ -1185,7 +1199,8 @@ mono_wasm_exec_regression (int verbose_level, char *image) EMSCRIPTEN_KEEPALIVE int mono_wasm_exit (int exit_code) { - mono_jit_cleanup (root_domain); + // TODO!!!!! call this on deputy thread + // mono_jit_cleanup (root_domain); fflush (stdout); fflush (stderr); emscripten_force_exit (exit_code); diff --git a/src/mono/wasm/runtime/exports-binding.ts b/src/mono/wasm/runtime/exports-binding.ts index 5fbfc421a9a570..663884039069a7 100644 --- a/src/mono/wasm/runtime/exports-binding.ts +++ b/src/mono/wasm/runtime/exports-binding.ts @@ -25,6 +25,7 @@ import { mono_wasm_change_case, mono_wasm_change_case_invariant } from "./hybrid import { mono_wasm_compare_string, mono_wasm_ends_with, mono_wasm_starts_with, mono_wasm_index_of } from "./hybrid-globalization/collations"; import { mono_wasm_get_calendar_info } from "./hybrid-globalization/calendar"; import { mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop } from "./pthreads/shared"; +import { mono_wasm_setup_deputy_thread } from "./pthreads/browser/deputy"; import { mono_wasm_invoke_js_blazor, mono_wasm_invoke_js_with_args_ref, mono_wasm_get_object_property_ref, mono_wasm_set_object_property_ref, @@ -51,6 +52,7 @@ export const mono_wasm_threads_imports = !MonoWasmThreads ? [] : [ mono_wasm_diagnostic_server_stream_signal_work_available, // corebindings.c + mono_wasm_setup_deputy_thread, mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop, ]; diff --git a/src/mono/wasm/runtime/globals.ts b/src/mono/wasm/runtime/globals.ts index 5554344dd5b11e..bbcdcb126ae66a 100644 --- a/src/mono/wasm/runtime/globals.ts +++ b/src/mono/wasm/runtime/globals.ts @@ -71,6 +71,8 @@ export function setRuntimeGlobals(globalObjects: GlobalObjects) { afterPreInit: createPromiseController(), afterPreRun: createPromiseController(), beforeOnRuntimeInitialized: createPromiseController(), + afterStartMonoVM: createPromiseController(), + runMainResult: createPromiseController(), afterOnRuntimeInitialized: createPromiseController(), afterPostRun: createPromiseController(), mono_wasm_exit: () => { diff --git a/src/mono/wasm/runtime/loader/config.ts b/src/mono/wasm/runtime/loader/config.ts index e805223074bccd..a0e89798bf6369 100644 --- a/src/mono/wasm/runtime/loader/config.ts +++ b/src/mono/wasm/runtime/loader/config.ts @@ -190,7 +190,7 @@ export function normalizeConfig() { if (MonoWasmThreads && !Number.isInteger(config.pthreadPoolSize)) { // ActiveIssue https://github.com/dotnet/runtime/issues/91538 - config.pthreadPoolSize = 40; + config.pthreadPoolSize = 1; } // Default values (when WasmDebugLevel is not set) diff --git a/src/mono/wasm/runtime/profiler.ts b/src/mono/wasm/runtime/profiler.ts index af4775f66fe974..b49d0ad044a4f7 100644 --- a/src/mono/wasm/runtime/profiler.ts +++ b/src/mono/wasm/runtime/profiler.ts @@ -43,7 +43,7 @@ export const enum MeasuredBlock { preRunWorker = "mono.preRunWorker", onRuntimeInitialized = "mono.onRuntimeInitialized", postRun = "mono.postRun", - memorySnapshot = "mono.memorySnapshot", + startMonoVM = "mono.startMonoVM", loadRuntime = "mono.loadRuntime", bindingsInit = "mono.bindingsInit", bindJsFunction = "mono.bindJsFunction:", diff --git a/src/mono/wasm/runtime/pthreads/browser/deputy.ts b/src/mono/wasm/runtime/pthreads/browser/deputy.ts new file mode 100644 index 00000000000000..fd4ac33b4b5958 --- /dev/null +++ b/src/mono/wasm/runtime/pthreads/browser/deputy.ts @@ -0,0 +1,101 @@ +import MonoWasmThreads from "consts:monoWasmThreads"; + +import { threads_c_functions as cwraps } from "../../cwraps"; +import { forceThreadMemoryViewRefresh, getI32, withStackAlloc } from "../../memory"; +import { Module, mono_assert, runtimeHelpers } from "../../globals"; +import { Thread, waitForThread } from "."; +import { mono_log_info } from "../../logging"; +import { start_mono_vm } from "../../startup"; +import { pthread_self } from "../worker"; +import { MonoThreadMessage, mono_wasm_install_js_worker_interop } from "../shared"; +import { mono_run_main_impl } from "../../run"; + +export let deputyThread: Thread | undefined; + +export async function startDeputyThread(): Promise { + if (!MonoWasmThreads) { + return; + } + const sizeOfPthreadT = 4; + const result: number | undefined = withStackAlloc(sizeOfPthreadT, (pthreadIdPtr) => { + if (!cwraps.mono_wasm_create_deputy_thread(pthreadIdPtr)) + return undefined; + const pthreadId = getI32(pthreadIdPtr); + return pthreadId; + }); + mono_assert(result, "failed to create deputy thread"); + // have to wait until the message port is created + deputyThread = await waitForThread(result); + // wait until mono VM started + await runtimeHelpers.afterStartMonoVM.promise; +} + +export async function deputy_run_main(main_assembly_name: string, args: string[]) { + deputyThread?.postMessageToWorker({ + type: "deputy", + cmd: "run_main", + main_assembly_name, + args + }); + return runtimeHelpers.runMainResult.promise; +} + +export function mono_wasm_setup_deputy_thread() { + mono_assert(MonoWasmThreads, "Expected MT build"); + if (globalThis.setInterval) globalThis.setInterval(() => { + mono_log_info("Deputy thread is alive!"); + }, 3000); + + runtimeHelpers.isDeputyThread = true; + + //TODO pop on exit + Module.runtimeKeepalivePush(); + + pthread_self.addEventListenerFromBrowser(async (event: MessageEvent) => { + if (event.data.type == "deputy" && event.data.cmd == "run_main") { + try { + forceThreadMemoryViewRefresh(); + const { main_assembly_name, args } = event.data as any; + const result = await mono_run_main_impl(main_assembly_name, args); + pthread_self.postMessageToBrowser({ + type: "deputy", + cmd: "run_main_result", + result + }); + } + catch (ex: any) { + pthread_self.postMessageToBrowser({ + type: "deputy", + cmd: "run_main_error", + reason: "" + ex + }); + } + } + }); + + + // because this is synchronous method, we will postpone mono startup to the next event loop + Module.safeSetTimeout(async () => { + try { + forceThreadMemoryViewRefresh(); + await start_mono_vm(); + + mono_wasm_install_js_worker_interop(1); + runtimeHelpers.javaScriptExports.install_synchronization_context(); + + // tell UI thread that we are ready + pthread_self.postMessageToBrowser({ + type: "deputy", + cmd: "ready" + }); + } + catch (ex: any) { + pthread_self.postMessageToBrowser({ + type: "deputy", + cmd: "abort", + reason: "" + ex + }); + runtimeHelpers.abort(ex); + } + }, 0); +} diff --git a/src/mono/wasm/runtime/pthreads/browser/index.ts b/src/mono/wasm/runtime/pthreads/browser/index.ts index 89c84baf78836e..dbcd79c85b5155 100644 --- a/src/mono/wasm/runtime/pthreads/browser/index.ts +++ b/src/mono/wasm/runtime/pthreads/browser/index.ts @@ -1,13 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { isMonoWorkerMessageChannelCreated, monoSymbol, makeMonoThreadMessageApplyMonoConfig, isMonoWorkerMessagePreload, MonoWorkerMessage } from "../shared"; +import MonoWasmThreads from "consts:monoWasmThreads"; + +import { isMonoWorkerMessageChannelCreated, monoSymbol, makeMonoThreadMessageApplyMonoConfig, isMonoWorkerMessagePreload, MonoWorkerMessage, getBrowserThreadID } from "../shared"; import { pthreadPtr } from "../shared/types"; import { MonoThreadMessage } from "../shared"; import Internals from "../shared/emscripten-internals"; import { createPromiseController, runtimeHelpers } from "../../globals"; import { PromiseController } from "../../types/internal"; -import { mono_log_debug } from "../../logging"; +import { mono_log_debug, mono_set_thread_id } from "../../logging"; +import { mono_wasm_init_diagnostics } from "../../diagnostics"; +import { startDeputyThread } from "./deputy"; const threads: Map = new Map(); @@ -80,8 +84,23 @@ export function getThread(pthreadPtr: pthreadPtr): Thread | undefined { export const getThreadIds = (): IterableIterator => threads.keys(); function monoDedicatedChannelMessageFromWorkerToMain(event: MessageEvent, thread: Thread): void { - // TODO: add callbacks that will be called from here - mono_log_debug("got message from worker on the dedicated channel", event.data, thread); + const data = event.data as MonoThreadMessage; + if (data.type == "deputy") { + if (data.cmd == "ready") { + runtimeHelpers.afterStartMonoVM.promise_control.resolve(); + return; + } else if (data.cmd == "abort") { + runtimeHelpers.afterStartMonoVM.promise_control.reject((data as any).reason); + return; + } else if (data.cmd == "run_main_result") { + runtimeHelpers.runMainResult.promise_control.resolve((data as any).result); + return; + } else if (data.cmd == "run_main_error") { + runtimeHelpers.runMainResult.promise_control.reject((data as any).reason); + return; + } + } + mono_log_debug("got unexpected message from worker on the dedicated channel", event.data, thread); } // handler that runs in the main thread when a message is received from a pthread worker @@ -132,3 +151,17 @@ export async function instantiateWasmPThreadWorkerPool(): Promise { await Promise.all(promises); } } + +export async function mono_wasm_init_threads() { + if (!MonoWasmThreads) { + return; + } + const tid = getBrowserThreadID(); + mono_set_thread_id(`0x${tid.toString(16)}-UI`); + + await instantiateWasmPThreadWorkerPool(); + + await mono_wasm_init_diagnostics(); + + await startDeputyThread(); +} diff --git a/src/mono/wasm/runtime/pthreads/shared/index.ts b/src/mono/wasm/runtime/pthreads/shared/index.ts index c8557755062a2f..24a24bad4aa003 100644 --- a/src/mono/wasm/runtime/pthreads/shared/index.ts +++ b/src/mono/wasm/runtime/pthreads/shared/index.ts @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. import MonoWasmThreads from "consts:monoWasmThreads"; -import BuildConfiguration from "consts:configuration"; import { Module, mono_assert, runtimeHelpers } from "../../globals"; import { MonoConfig } from "../../types"; @@ -47,6 +46,11 @@ export interface MonoThreadMessage { cmd: string; } +export interface DeputyMessage extends MonoThreadMessage { + type: "deputy"; + cmd: string; +} + export function isMonoThreadMessage(x: unknown): x is MonoThreadMessage { if (typeof (x) !== "object" || x === null) { return false; @@ -147,7 +151,7 @@ export function mono_wasm_install_js_worker_interop(install_js_synchronization_c Module.runtimeKeepalivePush(); } - set_thread_info(pthread_self ? pthread_self.pthreadId : 0, true, true, !!install_js_synchronization_context); + set_thread_info(pthread_self ? pthread_self.pthreadId : 0, true, true, !!install_js_synchronization_context, !!runtimeHelpers.isDeputyThread); } export function mono_wasm_uninstall_js_worker_interop(uninstall_js_synchronization_context: number): void { @@ -162,7 +166,7 @@ export function mono_wasm_uninstall_js_worker_interop(uninstall_js_synchronizati runtimeHelpers.jsSynchronizationContextInstalled = false; runtimeHelpers.mono_wasm_bindings_is_ready = false; - set_thread_info(pthread_self ? pthread_self.pthreadId : 0, true, false, false); + set_thread_info(pthread_self ? pthread_self.pthreadId : 0, true, false, false, false); } export function assert_synchronization_context(): void { @@ -171,14 +175,18 @@ export function assert_synchronization_context(): void { } } +let info_counter = 0; // this is just for Debug build of the runtime, making it easier to debug worker threads -export function set_thread_info(pthread_ptr: number, isAttached: boolean, hasInterop: boolean, hasSynchronization: boolean): void { - if (MonoWasmThreads && BuildConfiguration === "Debug" && !runtimeHelpers.cspPolicy) { +export function set_thread_info(pthread_ptr: number, isAttached: boolean, hasInterop: boolean, hasSynchronization: boolean, isDeputy: boolean): void { + // TODO && BuildConfiguration === "Debug" + if (MonoWasmThreads && !runtimeHelpers.cspPolicy) { + const id = "0x" + pthread_ptr.toString(16); try { - (globalThis as any).monoThreadInfo = new Function(`//# sourceURL=https://WorkerInfo/\r\nconsole.log("tid:0x${pthread_ptr.toString(16)} isAttached:${isAttached} hasInterop:${!!hasInterop} hasSynchronization:${hasSynchronization}" );`); + (globalThis as any).monoThreadInfo = new Function(`//# sourceURL=https://WorkerInfo-${info_counter}-${id}/\r\nreturn("id:${id} isAttached:${isAttached} hasInterop:${!!hasInterop} hasSynchronization:${hasSynchronization} isDeputy:${isDeputy}" );`); } catch (ex) { runtimeHelpers.cspPolicy = true; } } + info_counter++; } diff --git a/src/mono/wasm/runtime/pthreads/worker/index.ts b/src/mono/wasm/runtime/pthreads/worker/index.ts index 2ac8feb10a9a54..3d595afdc48e2b 100644 --- a/src/mono/wasm/runtime/pthreads/worker/index.ts +++ b/src/mono/wasm/runtime/pthreads/worker/index.ts @@ -18,7 +18,7 @@ import { WorkerThreadEventTarget } from "./events"; import { postRunWorker, preRunWorker } from "../../startup"; -import { mono_log_debug } from "../../logging"; +import { mono_log_debug, mono_log_info } from "../../logging"; import { mono_set_thread_id } from "../../logging"; import { jiterpreter_allocate_tables } from "../../jiterpreter-support"; @@ -85,23 +85,36 @@ function setupChannelToMainThread(pthread_ptr: pthreadPtr): PThreadSelf { /// This is an implementation detail function. /// Called in the worker thread (not main thread) from mono when a pthread becomes attached to the mono runtime. +let inter: number | undefined; export function mono_wasm_pthread_on_pthread_attached(pthread_id: number): void { const self = pthread_self; mono_assert(self !== null && self.pthreadId == pthread_id, "expected pthread_self to be set already when attaching"); - mono_set_thread_id("0x" + pthread_id.toString(16)); - mono_log_debug("attaching pthread to mono runtime 0x" + pthread_id.toString(16)); + const id = "0x" + pthread_id.toString(16); + mono_set_thread_id(id); + mono_log_info("attaching pthread to mono runtime " + id); preRunWorker(); - set_thread_info(pthread_id, true, false, false); + set_thread_info(pthread_id, true, false, false, false); jiterpreter_allocate_tables(Module); currentWorkerThreadEvents.dispatchEvent(makeWorkerThreadEvent(dotnetPthreadAttached, self)); + if (globalThis.setInterval) { + const info = (globalThis as any).monoThreadInfo ? + (globalThis as any).monoThreadInfo() : "" + id; + inter = globalThis.setInterval(() => { + mono_log_info("Worker is alive! " + info); + }, 3000); // keep the worker alive + } } /// Called in the worker thread (not main thread) from mono when a pthread becomes detached from the mono runtime. export function mono_wasm_pthread_on_pthread_detached(pthread_id: number): void { - mono_log_debug("detaching pthread from mono runtime 0x" + pthread_id.toString(16)); + mono_log_info("detaching pthread from mono runtime 0x" + pthread_id.toString(16)); postRunWorker(); - set_thread_info(pthread_id, false, false, false); + set_thread_info(pthread_id, false, false, false, false); mono_set_thread_id(""); + if (inter && (globalThis as any).clearInterval) { + clearInterval(inter); + inter = undefined; + } } /// This is an implementation detail function. diff --git a/src/mono/wasm/runtime/run.ts b/src/mono/wasm/runtime/run.ts index 41444a5251f8cb..7455071e4b5cf0 100644 --- a/src/mono/wasm/runtime/run.ts +++ b/src/mono/wasm/runtime/run.ts @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +import MonoWasmThreads from "consts:monoWasmThreads"; + import { ENVIRONMENT_IS_NODE, loaderHelpers, runtimeHelpers } from "./globals"; import { mono_wasm_wait_for_debugger } from "./debug"; import { mono_wasm_set_main_args } from "./startup"; @@ -8,6 +10,7 @@ import cwraps from "./cwraps"; import { assembly_load } from "./class-loader"; import { mono_log_info } from "./logging"; import { assert_bindings } from "./invoke-js"; +import { deputy_run_main } from "./pthreads/browser/deputy"; /** * Possible signatures are described here https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line @@ -54,6 +57,15 @@ export async function mono_run_main(main_assembly_name: string, args?: string[]) mono_log_info("waiting for debugger..."); await mono_wasm_wait_for_debugger(); } + if (MonoWasmThreads) { + return deputy_run_main(main_assembly_name, args); + } + else { + return mono_run_main_impl(main_assembly_name, args); + } +} + +export async function mono_run_main_impl(main_assembly_name: string, args: string[]) { const method = find_entry_point(main_assembly_name); const res = await runtimeHelpers.javaScriptExports.call_entry_point(method, args); diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index 7fec1577dedc94..1fee0065ec7349 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -6,7 +6,8 @@ import WasmEnableLegacyJsInterop from "consts:wasmEnableLegacyJsInterop"; import { DotnetModuleInternal, CharPtrNull } from "./types/internal"; import { linkerDisableLegacyJsInterop, ENVIRONMENT_IS_PTHREAD, exportedRuntimeAPI, INTERNAL, loaderHelpers, Module, runtimeHelpers, createPromiseController, mono_assert, linkerWasmEnableSIMD, linkerWasmEnableEH, ENVIRONMENT_IS_WORKER } from "./globals"; -import cwraps, { init_c_exports } from "./cwraps"; +import { init_c_exports } from "./cwraps"; +import { threads_c_functions as cwraps } from "./cwraps"; import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug"; import { toBase64StringImpl } from "./base64"; import { mono_wasm_init_aot_profiler, mono_wasm_init_browser_profiler } from "./profiler"; @@ -18,17 +19,15 @@ import { init_managed_exports } from "./managed-exports"; import { cwraps_internal } from "./exports-internal"; import { CharPtr, InstantiateWasmCallBack, InstantiateWasmSuccessCallback } from "./types/emscripten"; import { wait_for_all_assets } from "./assets"; -import { mono_wasm_init_diagnostics } from "./diagnostics"; import { replace_linker_placeholders } from "./exports-binding"; import { endMeasure, MeasuredBlock, startMeasure } from "./profiler"; import { checkMemorySnapshotSize, getMemorySnapshot, storeMemorySnapshot } from "./snapshot"; import { interp_pgo_load_data, interp_pgo_save_data } from "./interp-pgo"; -import { mono_log_debug, mono_log_error, mono_log_warn, mono_set_thread_id } from "./logging"; +import { mono_log_debug, mono_log_error, mono_log_warn } from "./logging"; // threads -import { preAllocatePThreadWorkerPool, instantiateWasmPThreadWorkerPool } from "./pthreads/browser"; +import { mono_wasm_init_threads, preAllocatePThreadWorkerPool } from "./pthreads/browser"; import { currentWorkerThreadEvents, dotnetPthreadCreated, initWorkerThreadEvents } from "./pthreads/worker"; -import { getBrowserThreadID } from "./pthreads/shared"; import { jiterpreter_allocate_tables } from "./jiterpreter-support"; // legacy @@ -145,6 +144,9 @@ function preInit(userPreInit: (() => void)[]) { mono_wasm_pre_init_essential(false); mono_log_debug("preInit"); runtimeHelpers.beforePreInit.promise_control.resolve(); + if (!ENVIRONMENT_IS_WORKER) { + Module.runtimeKeepalivePush(); + } // all user Module.preInit callbacks userPreInit.forEach(fn => fn()); } catch (err) { @@ -237,33 +239,23 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) { await wait_for_all_assets(); - // Threads early are not supported with memory snapshot. See below how we enable them later. - // Please disable startupMemoryCache in order to be able to diagnose or pause runtime startup. - if (MonoWasmThreads && !runtimeHelpers.config.startupMemoryCache) { - await mono_wasm_init_threads(); - } - - // load runtime and apply environment settings (if necessary) - await mono_wasm_before_memory_snapshot(); - - if (runtimeHelpers.config.interpreterPgo) { - await interp_pgo_load_data(); - } + mono_assert(!MonoWasmThreads || !runtimeHelpers.config.startupMemoryCache, "Threads are not supported with memory snapshot."); - if (runtimeHelpers.config.exitAfterSnapshot) { - const reason = runtimeHelpers.ExitStatus - ? new runtimeHelpers.ExitStatus(0) - : new Error("Snapshot taken, exiting because exitAfterSnapshot was set."); - reason.silent = true; + if (MonoWasmThreads) { + await mono_wasm_init_threads(); + } else { + await start_mono_vm(); - loaderHelpers.mono_exit(0, reason); - return; - } + if (runtimeHelpers.config.exitAfterSnapshot) { + const reason = runtimeHelpers.ExitStatus + ? new runtimeHelpers.ExitStatus(0) + : new Error("Snapshot taken, exiting because exitAfterSnapshot was set."); + reason.silent = true; - if (!ENVIRONMENT_IS_WORKER) { - Module.runtimeKeepalivePush(); + loaderHelpers.mono_exit(0, reason); + return; + } } - runtimeHelpers.runtimeReady = true; if (runtimeHelpers.config.virtualWorkingDirectory) { const FS = Module.FS; @@ -276,17 +268,8 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) { FS.chdir(cwd); } - if (MonoWasmThreads && runtimeHelpers.config.startupMemoryCache) { - await mono_wasm_init_threads(); - } - - bindings_init(); - jiterpreter_allocate_tables(Module); + runtimeHelpers.runtimeReady = true; - if (MonoWasmThreads) { - runtimeHelpers.javaScriptExports.install_synchronization_context(); - runtimeHelpers.jsSynchronizationContextInstalled = true; - } if (!runtimeHelpers.mono_wasm_runtime_is_ready) mono_wasm_runtime_ready(); @@ -348,16 +331,6 @@ export function postRunWorker() { runtimeHelpers.afterPreRun = createPromiseController(); } -async function mono_wasm_init_threads() { - if (!MonoWasmThreads) { - return; - } - const tid = getBrowserThreadID(); - mono_set_thread_id(`0x${tid.toString(16)}-main`); - await instantiateWasmPThreadWorkerPool(); - await mono_wasm_init_diagnostics(); -} - function mono_wasm_pre_init_essential(isWorker: boolean): void { if (!isWorker) Module.addRunDependency("mono_wasm_pre_init_essential"); @@ -377,11 +350,6 @@ function mono_wasm_pre_init_essential(isWorker: boolean): void { cwraps_mono_api(MONO); cwraps_binding_api(BINDING); } - // removeRunDependency triggers the dependenciesFulfilled callback (runCaller) in - // emscripten - on a worker since we don't have any other dependencies that causes run() to get - // called too soon; and then it will get called a second time when dotnet.native.js calls it directly. - // on a worker run() short-cirtcuits and just calls readyPromiseResolve, initRuntime and postMessage. - // sending postMessage twice will break instantiateWasmPThreadWorkerPool on the main thread. if (!isWorker) Module.removeRunDependency("mono_wasm_pre_init_essential"); } @@ -512,7 +480,7 @@ async function ensureUsedWasmFeatures() { } } -async function mono_wasm_before_memory_snapshot() { +export async function start_mono_vm() { const mark = startMeasure(); if (runtimeHelpers.loadedMemorySnapshotSize) { // get the bytes after we re-sized the memory, so that we don't have too much memory in use at the same time @@ -550,13 +518,19 @@ async function mono_wasm_before_memory_snapshot() { runtimeHelpers.storeMemorySnapshotPending = false; } - if (runtimeHelpers.config.interpreterPgo) + if (runtimeHelpers.config.interpreterPgo) { + await interp_pgo_load_data(); + setTimeout(maybeSaveInterpPgoTable, (runtimeHelpers.config.interpreterPgoSaveDelay || 15) * 1000); + } + + bindings_init(); + jiterpreter_allocate_tables(Module); - endMeasure(mark, MeasuredBlock.memorySnapshot); + endMeasure(mark, MeasuredBlock.startMonoVM); } -async function maybeSaveInterpPgoTable () { +async function maybeSaveInterpPgoTable() { // If the application exited abnormally, don't save the table. It probably doesn't contain useful data, // and saving would overwrite any existing table from a previous successful run. // We treat exiting with a code of 0 as equivalent to if the app is still running - it's perfectly fine diff --git a/src/mono/wasm/runtime/types/internal.ts b/src/mono/wasm/runtime/types/internal.ts index 53fb458d6a4323..d1fe89ef256a2d 100644 --- a/src/mono/wasm/runtime/types/internal.ts +++ b/src/mono/wasm/runtime/types/internal.ts @@ -191,6 +191,7 @@ export type RuntimeHelpers = { subtle: SubtleCrypto | null, updateMemoryViews: () => void runtimeReady: boolean, + isDeputyThread: boolean, jsSynchronizationContextInstalled: boolean, cspPolicy: boolean, @@ -201,9 +202,12 @@ export type RuntimeHelpers = { afterPreInit: PromiseAndController, afterPreRun: PromiseAndController, beforeOnRuntimeInitialized: PromiseAndController, + afterStartMonoVM: PromiseAndController, afterOnRuntimeInitialized: PromiseAndController, afterPostRun: PromiseAndController, + runMainResult: PromiseAndController, + featureWasmEh: boolean, featureWasmSimd: boolean, diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 4467dc20ce204e..ffb2e0536c1bb4 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -277,7 +277,7 @@ function configureRuntime(dotnet, runArgs) { .withInteropCleanupOnExit() .withAssertAfterExit() .withConfig({ - loadAllSatelliteResources: true + loadAllSatelliteResources: true, }); if (ENVIRONMENT_IS_NODE) { @@ -326,7 +326,6 @@ async function dry_run(runArgs) { appendElementOnExit: false, logExitCode: false, virtualWorkingDirectory: undefined, - pthreadPoolSize: 0, interopCleanupOnExit: false, // this just means to not continue startup after the snapshot is taken. // If there was previously a matching snapshot, it will be used. @@ -343,6 +342,13 @@ async function dry_run(runArgs) { return true; } +let alive; +if (globalThis.setInterval) { + alive = globalThis.setInterval(() => { + console.log("UI thread is alive!"); + }, 3000); +} + async function run() { try { const runArgs = await getArgs(); @@ -350,11 +356,11 @@ async function run() { if (ENVIRONMENT_IS_WEB && runArgs.memorySnapshot) { if (globalThis.isSecureContext) { - const dryOk = await dry_run(runArgs); - if (!dryOk) { - mono_exit(1, "Failed during dry run"); - return; - } + const dryOk = await dry_run(runArgs); + if (!dryOk) { + mono_exit(1, "Failed during dry run"); + return; + } } else { console.log("Skipping dry run as the context is not secure and the snapshot would be not trusted."); } @@ -411,6 +417,9 @@ async function run() { const app_args = runArgs.applicationArguments.slice(2); const result = await App.runtime.runMain(main_assembly_name, app_args); console.log(`test-main.js exiting ${app_args.length > 1 ? main_assembly_name + " " + app_args[0] : main_assembly_name} with result ${result}`); + if (alive && globalThis.clearInterval) { + globalThis.clearInterval(alive); + } mono_exit(result); } catch (error) { if (error.name != "ExitStatus") { @@ -425,4 +434,5 @@ async function run() { } } + await run(); diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 6ed392341e6b66..e537019944009d 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -274,7 +274,7 @@ <_EmccCommonFlags Condition="'$(MonoWasmThreads)' == 'true'" Include="-s USE_PTHREADS=1" /> <_EmccLinkFlags Condition="'$(MonoWasmThreads)' == 'true'" Include="-Wno-pthreads-mem-growth" /> <_EmccLinkFlags Condition="'$(MonoWasmThreads)' == 'true'" Include="-s PTHREAD_POOL_SIZE=0" /> - <_EmccLinkFlags Condition="'$(MonoWasmThreads)' == 'true'" Include="-s PTHREAD_POOL_SIZE_STRICT=2" /> + <_EmccLinkFlags Condition="'$(MonoWasmThreads)' == 'true'" Include="-s PTHREAD_POOL_SIZE_STRICT=0" /> <_EmccLinkFlags Include="-s ALLOW_MEMORY_GROWTH=1" /> <_EmccLinkFlags Include="-s ALLOW_TABLE_GROWTH=1" />