diff --git a/NuGet.config b/NuGet.config index 90e21e18c5bffd..6544a77805caf6 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b64486cec2ab43..e04ddefbde4dcd 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,24 +1,24 @@ - + https://github.com/dotnet/icu - cff1c9ff20d271c6698d150e484e8327998595a4 + 18b103db239331f9b917e741b13c95eddf32f6df https://github.com/dotnet/msquic 7312355e44fd230b7aa26c7190f3870391751476 - + https://github.com/dotnet/emsdk - 6c7f38c614304c93cd392907df7d5e770d5cf7f1 + 864fae9e00da58498da19b40d46be706a9bf5f47 - + https://github.com/dotnet/emsdk - 6c7f38c614304c93cd392907df7d5e770d5cf7f1 + 864fae9e00da58498da19b40d46be706a9bf5f47 - + https://github.com/dotnet/emsdk - 6c7f38c614304c93cd392907df7d5e770d5cf7f1 + 864fae9e00da58498da19b40d46be706a9bf5f47 https://github.com/dotnet/wcf @@ -102,49 +102,49 @@ https://github.com/microsoft/vstest 140434f7109d357d0158ade9e5164a4861513965 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 https://github.com/dotnet/llvm-project @@ -242,13 +242,13 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization d50065944d8b41d804448a7056351481d583ad3d - + https://github.com/dotnet/hotreload-utils - 83c5bd71b65d9de362ae0ba2f2cdea94c002c8c7 + 2293d2ba069595f1c87f4e002c84cbab7201bfe7 - + https://github.com/dotnet/runtime-assets - 27b0291e9fb85b6664e4fc7c6bc10bcd059d8ab7 + 60b420e88cdd0ec0becb2115e14288adc1a1cb55 https://github.com/dotnet/roslyn-analyzers diff --git a/eng/Versions.props b/eng/Versions.props index 851a89e62004da..b45f75f0fa0d59 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -108,18 +108,18 @@ 4.5.0 6.0.0-rc.1.21415.6 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 - 6.0.0-beta.23212.1 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 + 6.0.0-beta.23316.2 1.0.0-prerelease.21416.5 1.0.0-prerelease.21416.5 @@ -162,7 +162,7 @@ 6.0.100-1.21459.1 $(MicrosoftNETILLinkTasksVersion) - 6.0.0-rtm.23218.5 + 6.0.0-rtm.23315.1 6.0.0-servicing.22205.1 @@ -175,9 +175,9 @@ 11.1.0-alpha.1.21416.1 11.1.0-alpha.1.21416.1 - 6.0.20 - 6.0.20 - 6.0.20 + 6.0.21 + 6.0.21 + 6.0.21 $(MicrosoftNETWorkloadEmscriptenManifest60100Version) 1.1.87-gba258badda diff --git a/src/coreclr/System.Private.CoreLib/src/System/GC.cs b/src/coreclr/System.Private.CoreLib/src/System/GC.cs index bcbf042fd1b24d..33594cca7170ae 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/GC.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/GC.cs @@ -719,5 +719,13 @@ public static T[] AllocateArray(int length, bool pinned = false) // T[] rathe return Unsafe.As(AllocateNewArray(typeof(T[]).TypeHandle.Value, length, flags)); } + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern long _GetTotalPauseDuration(); + + public static TimeSpan GetTotalPauseDuration() + { + return new TimeSpan(_GetTotalPauseDuration()); + } } } diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 7400a2eae94882..df9a96b8dc0099 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -45045,6 +45045,11 @@ void GCHeap::GetMemoryInfo(uint64_t* highMemLoadThresholdBytes, #endif //_DEBUG } +int64_t GCHeap::GetTotalPauseDuration() +{ + return (int64_t)(gc_heap::total_suspended_time * 10); +} + uint32_t GCHeap::GetMemoryLoad() { uint32_t memory_load = 0; diff --git a/src/coreclr/gc/gcimpl.h b/src/coreclr/gc/gcimpl.h index 5f631642e11c76..1d470a0c8ca124 100644 --- a/src/coreclr/gc/gcimpl.h +++ b/src/coreclr/gc/gcimpl.h @@ -180,7 +180,9 @@ class GCHeap : public IGCHeapInternal bool* isConcurrent, uint64_t* genInfoRaw, uint64_t* pauseInfoRaw, - int kind);; + int kind); + + int64_t GetTotalPauseDuration(); uint32_t GetMemoryLoad(); diff --git a/src/coreclr/gc/gcinterface.h b/src/coreclr/gc/gcinterface.h index d7c08c44d9adce..03c56d49dbb531 100644 --- a/src/coreclr/gc/gcinterface.h +++ b/src/coreclr/gc/gcinterface.h @@ -925,6 +925,9 @@ class IGCHeap { IGCHeap() {} virtual ~IGCHeap() {} + + // Get the total paused duration + virtual int64_t GetTotalPauseDuration() = 0; }; #ifdef WRITE_BARRIER_CHECK diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index fec65f96e5928f..6b5bdde020abf6 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -674,6 +674,16 @@ UINT64 GCInterface::m_remPressure[MEM_PRESSURE_COUNT] = {0, 0, 0, 0}; // his // (m_iteration % MEM_PRESSURE_COUNT) is used as an index into m_addPressure and m_remPressure UINT GCInterface::m_iteration = 0; +FCIMPL0(INT64, GCInterface::GetTotalPauseDuration) +{ + FCALL_CONTRACT; + + FC_GC_POLL_NOT_NEEDED(); + + return GCHeapUtilities::GetGCHeap()->GetTotalPauseDuration(); +} +FCIMPLEND + FCIMPL2(void, GCInterface::GetMemoryInfo, Object* objUNSAFE, int kind) { FCALL_CONTRACT; diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index f59bbe7f66c118..666ed6aefcfc25 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -143,6 +143,7 @@ class GCInterface { static FORCEINLINE UINT64 InterlockedAdd(UINT64 *pAugend, UINT64 addend); static FORCEINLINE UINT64 InterlockedSub(UINT64 *pMinuend, UINT64 subtrahend); + static FCDECL0(INT64, GetTotalPauseDuration); static FCDECL2(void, GetMemoryInfo, Object* objUNSAFE, int kind); static FCDECL0(UINT32, GetMemoryLoad); static FCDECL0(int, GetGcLatencyMode); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 363ae6f6cfa7cc..8317386a22f722 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -706,6 +706,7 @@ FCFuncStart(gGCInterfaceFuncs) FCFuncElement("_WaitForFullGCComplete", GCInterface::WaitForFullGCComplete) FCFuncElement("_CollectionCount", GCInterface::CollectionCount) FCFuncElement("GetMemoryInfo", GCInterface::GetMemoryInfo) + FCFuncElement("_GetTotalPauseDuration", GCInterface::GetTotalPauseDuration) FCFuncElement("GetMemoryLoad", GCInterface::GetMemoryLoad) QCFuncElement("_StartNoGCRegion", GCInterface::StartNoGCRegion) QCFuncElement("_EndNoGCRegion", GCInterface::EndNoGCRegion) diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index b80a92093c2768..da5471f14df03f 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -20,7 +20,7 @@ $(AdditionalRuntimeIdentifiers);$(OutputRID) 11 - true + false diff --git a/src/libraries/System.Runtime/src/MatchingRefApiCompatBaseline.txt b/src/libraries/System.Runtime/src/MatchingRefApiCompatBaseline.txt index cbe8cabdbb2956..542d29445b645c 100644 --- a/src/libraries/System.Runtime/src/MatchingRefApiCompatBaseline.txt +++ b/src/libraries/System.Runtime/src/MatchingRefApiCompatBaseline.txt @@ -24,4 +24,5 @@ CannotMakeMemberAbstract : Member 'public System.Boolean System.IO.FileSystemInf CannotMakeMemberAbstract : Member 'public System.String System.IO.FileSystemInfo.Name.get()' is abstract in the reference but is not abstract in the implementation. # C# generates backing fields for fixed buffers as public. TypesMustExist : Type 'System.IO.Enumeration.FileSystemEntry.<_fileNameBuffer>e__FixedBuffer' does not exist in the reference but it does exist in the implementation. - +# This API only exists on servicing builds after the commit that introduce it +MembersMustExist : Member 'public System.TimeSpan System.GC.GetTotalPauseDuration()' does not exist in the reference but it does exist in the implementation. \ No newline at end of file diff --git a/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs b/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs index a92ebab49920d7..4a383c9efb7172 100644 --- a/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs @@ -313,5 +313,10 @@ internal static int GetLastGCPercentTimeInGC() { return (int)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.GC_LAST_PERCENT_TIME_IN_GC); } + + public static TimeSpan GetTotalPauseDuration() + { + return TimeSpan.Zero; + } } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index 950acbb2dcf915..aa33f94f5cd541 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -288,6 +289,7 @@ internal class ExecutionContext public object AuxData { get; set; } public PauseOnExceptionsKind PauseOnExceptions { get; set; } + internal bool Destroyed { get; set; } public List CallStack { get; set; } @@ -341,4 +343,70 @@ public PerScopeCache() { } } + + internal sealed class ConcurrentExecutionContextDictionary + { + private ConcurrentDictionary> contexts = new ConcurrentDictionary>(); + public ExecutionContext GetCurrentContext(SessionId sessionId) + => TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context) + ? context + : throw new KeyNotFoundException($"No execution context found for session {sessionId}"); + + public bool TryGetCurrentExecutionContextValue(SessionId id, out ExecutionContext executionContext, bool ignoreDestroyedContext = true) + { + executionContext = null; + if (!contexts.TryGetValue(id, out ConcurrentBag contextBag)) + return false; + if (contextBag.IsEmpty) + return false; + IEnumerable validContexts = null; + if (ignoreDestroyedContext) + validContexts = contextBag.Where(context => context.Destroyed == false); + else + validContexts = contextBag; + if (!validContexts.Any()) + return false; + int maxId = validContexts.Max(context => context.Id); + executionContext = contextBag.FirstOrDefault(context => context.Id == maxId); + return executionContext != null; + } + + public void OnDefaultContextUpdate(SessionId sessionId, ExecutionContext newContext) + { + if (TryGetAndAddContext(sessionId, newContext, out ExecutionContext previousContext)) + { + foreach (KeyValuePair kvp in previousContext.BreakpointRequests) + { + newContext.BreakpointRequests[kvp.Key] = kvp.Value.Clone(); + } + newContext.PauseOnExceptions = previousContext.PauseOnExceptions; + } + } + + public bool TryGetAndAddContext(SessionId sessionId, ExecutionContext newExecutionContext, out ExecutionContext previousExecutionContext) + { + bool hasExisting = TryGetCurrentExecutionContextValue(sessionId, out previousExecutionContext, ignoreDestroyedContext: false); + ConcurrentBag bag = contexts.GetOrAdd(sessionId, _ => new ConcurrentBag()); + bag.Add(newExecutionContext); + return hasExisting; + } + + public void DestroyContext(SessionId sessionId, int id) + { + if (!contexts.TryGetValue(sessionId, out ConcurrentBag contextBag)) + return; + foreach (ExecutionContext context in contextBag.Where(x => x.Id == id).ToList()) + context.Destroyed = true; + } + + public void ClearContexts(SessionId sessionId) + { + if (!contexts.TryGetValue(sessionId, out ConcurrentBag contextBag)) + return; + foreach (ExecutionContext context in contextBag) + context.Destroyed = true; + } + + public bool ContainsKey(SessionId sessionId) => contexts.ContainsKey(sessionId); + } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 7b2cc2bff517b1..36a6d8eea56fec 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -22,7 +22,7 @@ internal class MonoProxy : DevToolsProxy private IList urlSymbolServerList; private static HttpClient client = new HttpClient(); private HashSet sessions = new HashSet(); - private Dictionary contexts = new Dictionary(); + internal ConcurrentExecutionContextDictionary Contexts = new ConcurrentExecutionContextDictionary(); private const string sPauseOnUncaught = "pause_on_uncaught"; private const string sPauseOnCaught = "pause_on_caught"; @@ -32,21 +32,6 @@ public MonoProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList SdbHelper = new MonoSDBHelper(this, logger); } - internal ExecutionContext GetContext(SessionId sessionId) - { - if (contexts.TryGetValue(sessionId, out ExecutionContext context)) - return context; - - throw new ArgumentException($"Invalid Session: \"{sessionId}\"", nameof(sessionId)); - } - - private bool UpdateContext(SessionId sessionId, ExecutionContext executionContext, out ExecutionContext previousExecutionContext) - { - bool previous = contexts.TryGetValue(sessionId, out previousExecutionContext); - contexts[sessionId] = executionContext; - return previous; - } - internal Task SendMonoCommand(SessionId id, MonoCommands cmd, CancellationToken token) => SendCommand(id, "Runtime.evaluate", JObject.FromObject(cmd), token); protected override async Task AcceptEvent(SessionId sessionId, string method, JObject args, CancellationToken token) @@ -56,7 +41,7 @@ protected override async Task AcceptEvent(SessionId sessionId, string meth case "Runtime.consoleAPICalled": { // Don't process events from sessions we aren't tracking - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; string type = args["type"]?.ToString(); if (type == "debug") @@ -129,7 +114,7 @@ protected override async Task AcceptEvent(SessionId sessionId, string meth case "Runtime.exceptionThrown": { // Don't process events from sessions we aren't tracking - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; if (!context.IsRuntimeReady) @@ -141,10 +126,22 @@ protected override async Task AcceptEvent(SessionId sessionId, string meth break; } + case "Runtime.executionContextDestroyed": + { + Contexts.DestroyContext(sessionId, args["executionContextId"].Value()); + return false; + } + + case "Runtime.executionContextsCleared": + { + Contexts.ClearContexts(sessionId); + return false; + } + case "Debugger.paused": { // Don't process events from sessions we aren't tracking - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; if (args?["callFrames"]?.Value()?.Count == 0) @@ -238,7 +235,7 @@ protected override async Task AcceptEvent(SessionId sessionId, string meth private async Task IsRuntimeAlreadyReadyAlready(SessionId sessionId, CancellationToken token) { - if (contexts.TryGetValue(sessionId, out ExecutionContext context) && context.IsRuntimeReady) + if (Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context) && context.IsRuntimeReady) return true; Result res = await SendMonoCommand(sessionId, MonoCommands.IsRuntimeReady(), token); @@ -252,7 +249,7 @@ protected override async Task AcceptCommand(MessageId id, string method, J if (id == SessionId.Null) await AttachToTarget(id, token); - if (!contexts.TryGetValue(id, out ExecutionContext context)) + if (!Contexts.TryGetCurrentExecutionContextValue(id, out ExecutionContext context)) { // for Dotnetdebugger.* messages, treat them as handled, thus not passing them on to the browser return method.StartsWith("DotnetDebugger.", StringComparison.OrdinalIgnoreCase); @@ -607,7 +604,7 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation private async Task OnSetVariableValue(MessageId id, int scopeId, string varName, JToken varValue, CancellationToken token) { - ExecutionContext ctx = GetContext(id); + ExecutionContext ctx = Contexts.GetCurrentContext(id); Frame scope = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId); if (scope == null) return false; @@ -844,7 +841,7 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec if (res.IsErr) return false; - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); var retDebuggerCmd = new MemoryStream(newBytes); var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); @@ -910,7 +907,7 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec internal async Task LoadSymbolsOnDemand(AssemblyInfo asm, int method_token, SessionId sessionId, CancellationToken token) { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); if (urlSymbolServerList.Count == 0) return null; if (asm.TriedToLoadSymbolsOnDemand) @@ -961,14 +958,7 @@ internal async Task LoadSymbolsOnDemand(AssemblyInfo asm, int method private async Task OnDefaultContext(SessionId sessionId, ExecutionContext context, CancellationToken token) { Log("verbose", "Default context created, clearing state and sending events"); - if (UpdateContext(sessionId, context, out ExecutionContext previousContext)) - { - foreach (KeyValuePair kvp in previousContext.BreakpointRequests) - { - context.BreakpointRequests[kvp.Key] = kvp.Value.Clone(); - } - context.PauseOnExceptions = previousContext.PauseOnExceptions; - } + Contexts.OnDefaultContextUpdate(sessionId, context); if (await IsRuntimeAlreadyReadyAlready(sessionId, token)) await RuntimeReady(sessionId, token); @@ -976,7 +966,7 @@ private async Task OnDefaultContext(SessionId sessionId, ExecutionContext contex private async Task OnResume(MessageId msg_id, CancellationToken token) { - ExecutionContext ctx = GetContext(msg_id); + ExecutionContext ctx = Contexts.GetCurrentContext(msg_id); if (ctx.CallStack != null) { // Stopped on managed code @@ -985,12 +975,12 @@ private async Task OnResume(MessageId msg_id, CancellationToken token) //discard managed frames SdbHelper.ClearCache(); - GetContext(msg_id).ClearState(); + Contexts.GetCurrentContext(msg_id).ClearState(); } private async Task Step(MessageId msg_id, StepKind kind, CancellationToken token) { - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); if (context.CallStack == null) return false; @@ -1061,7 +1051,7 @@ private async Task OnAssemblyLoadedJSEvent(SessionId sessionId, JObject ev var assembly_data = Convert.FromBase64String(assembly_b64); var pdb_data = string.IsNullOrEmpty(pdb_b64) ? null : Convert.FromBase64String(pdb_b64); - var context = GetContext(sessionId); + var context = Contexts.GetCurrentContext(sessionId); foreach (var source in store.Add(sessionId, assembly_data, pdb_data)) { await OnSourceFileAdded(sessionId, source, context, token); @@ -1080,7 +1070,7 @@ private async Task OnEvaluateOnCallFrame(MessageId msg_id, int scopeId, st { try { - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); if (context.CallStack == null) return false; @@ -1121,7 +1111,7 @@ internal async Task GetScopeProperties(SessionId msg_id, int scopeId, Ca { try { - ExecutionContext ctx = GetContext(msg_id); + ExecutionContext ctx = Contexts.GetCurrentContext(msg_id); Frame scope = ctx.CallStack.FirstOrDefault(s => s.Id == scopeId); if (scope == null) return Result.Err(JObject.FromObject(new { message = $"Could not find scope with id #{scopeId}" })); @@ -1180,14 +1170,21 @@ private async Task OnSourceFileAdded(SessionId sessionId, SourceFile source, Exe { if (req.TryResolve(source)) { - await SetBreakpoint(sessionId, context.store, req, true, token); + try + { + await SetBreakpoint(sessionId, context.store, req, true, token); + } + catch (Exception e) + { + logger.LogDebug($"Unexpected error on OnSourceFileAdded {e}"); + } } } } internal async Task LoadStore(SessionId sessionId, CancellationToken token) { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); if (Interlocked.CompareExchange(ref context.store, new DebugStore(logger), null) != null) return await context.Source.Task; @@ -1239,7 +1236,7 @@ async Task GetLoadedFiles(SessionId sessionId, ExecutionContext contex private async Task RuntimeReady(SessionId sessionId, CancellationToken token) { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); if (Interlocked.CompareExchange(ref context.ready, new TaskCompletionSource(), null) != null) return await context.ready.Task; @@ -1263,7 +1260,7 @@ private async Task RuntimeReady(SessionId sessionId, CancellationTok private async Task ResetBreakpoint(SessionId msg_id, MethodInfo method, CancellationToken token) { - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); foreach (var req in context.BreakpointRequests.Values) { if (req.Method != null) @@ -1279,7 +1276,7 @@ private async Task RemoveBreakpoint(SessionId msg_id, JObject args, bool isEnCRe { string bpid = args?["breakpointId"]?.Value(); - ExecutionContext context = GetContext(msg_id); + ExecutionContext context = Contexts.GetCurrentContext(msg_id); if (!context.BreakpointRequests.TryGetValue(bpid, out BreakpointRequest breakpointRequest)) return; @@ -1303,7 +1300,7 @@ private async Task RemoveBreakpoint(SessionId msg_id, JObject args, bool isEnCRe private async Task SetBreakpoint(SessionId sessionId, DebugStore store, BreakpointRequest req, bool sendResolvedEvent, CancellationToken token) { - ExecutionContext context = GetContext(sessionId); + ExecutionContext context = Contexts.GetCurrentContext(sessionId); if (req.Locations.Any()) { Log("debug", $"locations already loaded for {req.Id}"); @@ -1319,7 +1316,7 @@ private async Task SetBreakpoint(SessionId sessionId, DebugStore store, Breakpoi .OrderBy(l => l.Column) .GroupBy(l => l.Id); - logger.LogDebug("BP request for '{req}' runtime ready {context.RuntimeReady}", req, GetContext(sessionId).IsRuntimeReady); + logger.LogDebug("BP request for '{req}' runtime ready {context.RuntimeReady}", req, Contexts.GetCurrentContext(sessionId).IsRuntimeReady); var breakpoints = new List(); @@ -1415,7 +1412,7 @@ private async Task AttachToTarget(SessionId sessionId, CancellationToken token) //we only need this check if it's a non-vs debugging if (sessionId == SessionId.Null) { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context) || context.PauseOnExceptions == PauseOnExceptionsKind.Unset) + if (!Contexts.TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context) || context.PauseOnExceptions == PauseOnExceptionsKind.Unset) { checkUncaughtExceptions = $"throw \"{sPauseOnUncaught}\";"; checkCaughtExceptions = $"try {{throw \"{sPauseOnCaught}\";}} catch {{}}"; diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 5390c58d5a3f5a..614bbd4738a46a 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -1408,7 +1408,7 @@ public async Task GetValueFromDebuggerDisplayAttribute(SessionId session var stringId = getCAttrsRetReader.ReadInt32(); var dispAttrStr = await GetStringValue(sessionId, stringId, token); - ExecutionContext context = proxy.GetContext(sessionId); + ExecutionContext context = proxy.Contexts.GetCurrentContext(sessionId); JArray objectValues = await GetObjectValues(sessionId, objectId, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.ForDebuggerDisplayAttribute, token); var thisObj = CreateJObject(value: "", type: "object", description: "", writable: false, objectId: $"dotnet:object:{objectId}"); diff --git a/src/tests/GC/API/GC/GetTotalPauseDuration.cs b/src/tests/GC/API/GC/GetTotalPauseDuration.cs new file mode 100644 index 00000000000000..96ac42640c804b --- /dev/null +++ b/src/tests/GC/API/GC/GetTotalPauseDuration.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// Tests GC.GetTotalPauseDuration() + +using System; +using System.Diagnostics; +using System.Reflection; + +public class Test_Collect +{ + public static int Main() + { + Stopwatch sw = Stopwatch.StartNew(); + GC.Collect(); + sw.Stop(); + TimeSpan elapsed = sw.Elapsed; + TimeSpan totalPauseDuration = (TimeSpan)typeof(GC).GetMethod("GetTotalPauseDuration", BindingFlags.Public | BindingFlags.Static).Invoke(null, null); + GCMemoryInfo memoryInfo = GC.GetGCMemoryInfo(); + TimeSpan lastGcDuration = memoryInfo.PauseDurations[0]; + + // These conditions assume the only GC in the process + // is the one we just triggered. This makes the test incompatible + // with any changes that might introduce extra GCs. + + if (TimeSpan.Zero < totalPauseDuration && + totalPauseDuration <= elapsed && + lastGcDuration == totalPauseDuration) + { + return 100; + } + else + { + return 101; + } + } +} diff --git a/src/tests/GC/API/GC/GetTotalPauseDuration.csproj b/src/tests/GC/API/GC/GetTotalPauseDuration.csproj new file mode 100644 index 00000000000000..358a5cea38bb5e --- /dev/null +++ b/src/tests/GC/API/GC/GetTotalPauseDuration.csproj @@ -0,0 +1,16 @@ + + + Exe + + true + + 0 + + + + PdbOnly + + + + +