This commit is contained in:
2026-06-30 12:13:11 +03:00
parent 3d0f97ade0
commit 0f4303bffd
2 changed files with 24 additions and 36 deletions
+2 -18
View File
@@ -2146,28 +2146,12 @@ public partial class EpConnection : NetworkConnection, IStore
} }
} }
//foreach (var x in _typeDefsByNameRequests.Values)
//{
// try
// {
// x.TriggerError(new AsyncException(ErrorType.Management, 0, "Connection closed"));
// }
// catch (Exception ex)
// {
// Global.Log(ex);
// }
//}
_requests.Clear(); _requests.Clear();
_resourceRequests.Clear(); _resourceRequests.Clear();
_typeDefRequests.Clear(); _typeDefRequests.Clear();
_fetchBlockedOn.Clear(); _resourcesFetchBlockedOn.Clear();
_typeDefFetchBlockedOn.Clear(); _typeDefsFetchBlockedOn.Clear();
//_typeDefsByIdRequests.Clear();
//_typeDefsByNameRequests.Clear();
foreach (var x in _attachedResources.Values) foreach (var x in _attachedResources.Values)
{ {
@@ -62,10 +62,10 @@ partial class EpConnection
// child resource ids its attachment is currently blocked on. Used to detect genuine cycles // child resource ids its attachment is currently blocked on. Used to detect genuine cycles
// (e.g. two concurrent fetches A<->B) so a placeholder can break the deadlock, while // (e.g. two concurrent fetches A<->B) so a placeholder can break the deadlock, while
// independent/app-facing fetches of an in-flight resource simply wait for full attachment. // independent/app-facing fetches of an in-flight resource simply wait for full attachment.
readonly Dictionary<uint, HashSet<uint>> _fetchBlockedOn = new Dictionary<uint, HashSet<uint>>(); readonly Dictionary<uint, HashSet<uint>> _resourcesFetchBlockedOn = new Dictionary<uint, HashSet<uint>>();
// Same wait-for graph as above, but for in-flight remote type definition parsing. // Same wait-for graph as above, but for in-flight remote type definition parsing.
readonly Dictionary<ulong, HashSet<ulong>> _typeDefFetchBlockedOn = new Dictionary<ulong, HashSet<ulong>>(); readonly Dictionary<ulong, HashSet<ulong>> _typeDefsFetchBlockedOn = new Dictionary<ulong, HashSet<ulong>>();
readonly object _deliveredRootsLock = new object(); readonly object _deliveredRootsLock = new object();
readonly Dictionary<uint, WeakReference<EpResource>> _deliveredRoots = new Dictionary<uint, WeakReference<EpResource>>(); readonly Dictionary<uint, WeakReference<EpResource>> _deliveredRoots = new Dictionary<uint, WeakReference<EpResource>>();
@@ -2092,9 +2092,9 @@ partial class EpConnection
set.Add(child); set.Add(child);
} }
void AddFetchBlock(uint parent, uint child) => AddFetchBlock(_fetchBlockedOn, parent, child); void AddResourceFetchBlock(uint parent, uint child) => AddFetchBlock(_resourcesFetchBlockedOn, parent, child);
void AddTypeDefFetchBlock(ulong parent, ulong child) => AddFetchBlock(_typeDefFetchBlockedOn, parent, child); void AddTypeDefFetchBlock(ulong parent, ulong child) => AddFetchBlock(_typeDefsFetchBlockedOn, parent, child);
// Removes a resource from the wait-for graph once it is attached or its fetch failed: it is // Removes a resource from the wait-for graph once it is attached or its fetch failed: it is
// no longer blocked on anything and no longer a pending child of anyone. // no longer blocked on anything and no longer a pending child of anyone.
@@ -2105,9 +2105,9 @@ partial class EpConnection
set.Remove(id); set.Remove(id);
} }
void ClearFetchNode(uint id) => ClearFetchNode(_fetchBlockedOn, id); void ClearResourceFetchNode(uint id) => ClearFetchNode(_resourcesFetchBlockedOn, id);
void ClearTypeDefFetchNode(ulong id) => ClearFetchNode(_typeDefFetchBlockedOn, id); void ClearTypeDefFetchNode(ulong id) => ClearFetchNode(_typeDefsFetchBlockedOn, id);
/// <summary> /// <summary>
/// Returns true if completing the fetch of <paramref name="id"/> by waiting for its in-flight /// Returns true if completing the fetch of <paramref name="id"/> by waiting for its in-flight
@@ -2270,7 +2270,7 @@ partial class EpConnection
var breakCycle = resource != null && DeadlockResolution switch var breakCycle = resource != null && DeadlockResolution switch
{ {
DeadlockResolutionMode.LegacyCrossChainPlaceholder => requestInfo.RequestSequence.Contains(id), DeadlockResolutionMode.LegacyCrossChainPlaceholder => requestInfo.RequestSequence.Contains(id),
DeadlockResolutionMode.WaitWithCycleDetection => HasWaitForCycle(id, requestSequence, _fetchBlockedOn), DeadlockResolutionMode.WaitWithCycleDetection => HasWaitForCycle(id, requestSequence, _resourcesFetchBlockedOn),
_ => false, _ => false,
}; };
@@ -2283,7 +2283,7 @@ partial class EpConnection
// is an unnecessary, partial delivery — the new resolver would have waited for full // is an unnecessary, partial delivery — the new resolver would have waited for full
// attachment instead. This counts the legacy resolver's over-eager placeholders. // attachment instead. This counts the legacy resolver's over-eager placeholders.
if (DeadlockResolution == DeadlockResolutionMode.LegacyCrossChainPlaceholder if (DeadlockResolution == DeadlockResolutionMode.LegacyCrossChainPlaceholder
&& !HasWaitForCycle(id, requestSequence, _fetchBlockedOn)) && !HasWaitForCycle(id, requestSequence, _resourcesFetchBlockedOn))
{ {
Global.Counters["EpResourceUnnecessaryPlaceholder"]++; Global.Counters["EpResourceUnnecessaryPlaceholder"]++;
UnnecessaryPlaceholderCount++; UnnecessaryPlaceholderCount++;
@@ -2296,7 +2296,7 @@ partial class EpConnection
// attachment to complete fully rather than exposing a partially attached resource. // attachment to complete fully rather than exposing a partially attached resource.
Global.Counters["EpResourcePendingCacheHit"]++; Global.Counters["EpResourcePendingCacheHit"]++;
if (parent != null) if (parent != null)
AddFetchBlock(parent.Value, id); AddResourceFetchBlock(parent.Value, id);
return requestInfo.Reply; return requestInfo.Reply;
} }
else if (resource != null && resource.Status != ResourceStatus.Suspended) else if (resource != null && resource.Status != ResourceStatus.Suspended)
@@ -2314,7 +2314,7 @@ partial class EpConnection
// This fetch's parent now waits on `id` until it attaches. // This fetch's parent now waits on `id` until it attaches.
if (parent != null) if (parent != null)
AddFetchBlock(parent.Value, id); AddResourceFetchBlock(parent.Value, id);
SendRequest(EpPacketRequest.AttachResource, id) SendRequest(EpPacketRequest.AttachResource, id)
.Then((result) => .Then((result) =>
@@ -2362,10 +2362,14 @@ partial class EpConnection
_neededResources.Remove(id); _neededResources.Remove(id);
_attachedResources[id] = new WeakReference<EpResource>(dr); _attachedResources[id] = new WeakReference<EpResource>(dr);
// attached: no longer part of the in-flight wait-for graph. // attached: no longer part of the in-flight wait-for graph.
ClearFetchNode(id); ClearResourceFetchNode(id);
TryPublishDeliveredRoots(); TryPublishDeliveredRoots();
reply.Trigger(dr); reply.Trigger(dr);
}).Error(ex => { _resourceRequests.Remove(id); ClearFetchNode(id); reply.TriggerError(ex); }); }).Error(ex => {
_resourceRequests.Remove(id);
ClearResourceFetchNode(id);
reply.TriggerError(ex);
});
}; };
if (typeDef == null) if (typeDef == null)
@@ -2427,7 +2431,7 @@ partial class EpConnection
// Failed to attach: drop the in-flight request and wait-for edges so a // Failed to attach: drop the in-flight request and wait-for edges so a
// later retry is not blocked by a stale entry. // later retry is not blocked by a stale entry.
_resourceRequests.Remove(id); _resourceRequests.Remove(id);
ClearFetchNode(id); ClearResourceFetchNode(id);
reply.TriggerError(ex); reply.TriggerError(ex);
}); });
@@ -2493,15 +2497,15 @@ partial class EpConnection
_resourceRequests.Remove(id); _resourceRequests.Remove(id);
_neededResources.Remove(id); _neededResources.Remove(id);
_attachedResources[id] = new WeakReference<EpResource>(resource); _attachedResources[id] = new WeakReference<EpResource>(resource);
ClearFetchNode(id); ClearResourceFetchNode(id);
TryPublishDeliveredRoots(); TryPublishDeliveredRoots();
reply.Trigger(resource); reply.Trigger(resource);
}) })
.Error(ex => { _resourceRequests.Remove(id); ClearFetchNode(id); reply.TriggerError(ex); }); .Error(ex => { _resourceRequests.Remove(id); ClearResourceFetchNode(id); reply.TriggerError(ex); });
}).Error(ex => }).Error(ex =>
{ {
_resourceRequests.Remove(id); _resourceRequests.Remove(id);
ClearFetchNode(id); ClearResourceFetchNode(id);
reply.TriggerError(ex); reply.TriggerError(ex);
}); });
@@ -2542,7 +2546,7 @@ partial class EpConnection
var breakCycle = typeDef != null && DeadlockResolution switch var breakCycle = typeDef != null && DeadlockResolution switch
{ {
DeadlockResolutionMode.LegacyCrossChainPlaceholder => requestInfo.RequestSequence.Contains(id), DeadlockResolutionMode.LegacyCrossChainPlaceholder => requestInfo.RequestSequence.Contains(id),
DeadlockResolutionMode.WaitWithCycleDetection => HasWaitForCycle(id, requestSequence, _typeDefFetchBlockedOn), DeadlockResolutionMode.WaitWithCycleDetection => HasWaitForCycle(id, requestSequence, _typeDefsFetchBlockedOn),
_ => false, _ => false,
}; };