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
+
+
+
+
+