Is there an existing issue for this?
What happened?
Under concurrent request load (reliably reproduced with a bulk file upload/overwrite through the Resource Manager / Digital Asset Manager), DotNetNuke.Common.Extensions.HttpContextDependencyInjectionExtensions.GetScope(HttpContextBase) calls itself with no recursion bound and never terminates. The IIS worker process crashes with a StackOverflowException (Windows exception code 0xC00000FD, uncatchable). Repeated crashes trip WAS Rapid-Fail Protection and take the whole application pool offline.
Steps to reproduce?
- Open a page hosting the Resource Manager (e.g. the Site Assets page).
- Select 100+ files whose names already exist in the target folder.
- Upload them, then click "Overwrite" on ~20+ of them in quick succession.
(This fires many concurrent POST /API/InternalServices/FileUpload/UploadFromLocal requests, multiplexed over one HTTP/2 connection.)
- The w3wp worker crashes with a stack overflow; a new worker starts, is hit by the same load, and crashes again ~every 90s (WAS Event 5011), until the app pool is disabled and the site returns 503.
A single-file upload never triggers it; only concurrent bulk uploads do.
Current Behavior
w3wp.exe crashes with exception code 0xC00000FD (STACK_OVERFLOW), faulting module mscorlib.ni.dll. The application pool enters a kill/restart loop (WAS Event 5011 roughly every 90 seconds) and eventually goes offline (503 / AppOffline). Because a StackOverflowException cannot be caught, nothing is logged by the application itself.
Expected Behavior
Concurrent requests that need the per-request DI scope resolve it safely and deterministically, with no unbounded recursion and no process crash.
Relevant log output
Windows System log (WAS), repeating ~every 90s:
Event 5011: A process serving application pool 'dnndev.me' suffered a fatal communication error with the Windows Process Activation Service. The process id was '...'.
Windows Application log:
Event 1000 (Application Error): Faulting application name: w3wp.exe ... Faulting module name: mscorlib.ni.dll ... Exception code: 0xc00000fd
Managed stack of the faulting thread (dotnet-dump 'clrstack'), ~5,104 repeated frames:
System.Collections.Hashtable.get_Item(System.Object)
DotNetNuke.Common.Extensions.HttpContextDependencyInjectionExtensions.GetScope(System.Collections.IDictionary)
DotNetNuke.Common.Extensions.HttpContextDependencyInjectionExtensions.GetScope(System.Web.HttpContextBase)
DotNetNuke.Common.Extensions.HttpContextDependencyInjectionExtensions.GetScope(System.Web.HttpContextBase)
... (× ~5,104) ...
Anything else?
ROOT CAUSE (deterministic) — ClearScope/DisposeScope remove the scope entry but leave the "GetScope_lock" sentinel in HttpContext.Items:
public static void ClearScope(this HttpContextBase httpContext)
{
httpContext.Items.Remove(typeof(IServiceScope)); // "GetScope_lock" is NOT removed
}
private static void DisposeScope(HttpContextBase httpContext)
{
httpContext.Items.GetScope()?.Dispose();
httpContext.ClearScope();
}
GetScope registers AddOnRequestCompleted(DisposeScope). After the request scope is disposed, Items[typeof(IServiceScope)] is gone but Items["GetScope_lock"] remains. Any later GetScope call then hits:
if (httpContext.Items.Contains("GetScope_lock")) return httpContext.GetScope();
and recurses forever -> StackOverflowException. Once GetScope runs after teardown, the crash is guaranteed (not a race).
OBSERVED TRIGGER (faulting-thread stack): a DI-activated service is resolved during an EndRequest module, after scope disposal:
GetScope(HttpContextBase) <- recurses 5,104x
DotNetNuke.Common.Globals.GetCurrentServiceProvider()
DotNetNuke.Entities.Modules.ModuleController..ctor(IEventLogger, IPermissionDefinitionService, IHostSettings)
DotNetNuke.Entities.Modules.ModuleController..ctor()
.ConfigurationController..ctor()
.SiteLogModule.OnEndRequest(object, EventArgs)
Constructing ModuleController via its parameterless ctor (which calls GetCurrentServiceProvider) after the scope is disposed is enough to hit this. Bulk file upload/overwrite reproduces it reliably.
MINIMAL FIX — clear the sentinel in ClearScope:
public static void ClearScope(this HttpContextBase httpContext)
{
httpContext.Items.Remove(typeof(IServiceScope));
httpContext.Items.Remove("GetScope_lock"); // add this
}
ROBUST FIX — also make the retry non-recursive and thread-safe (HttpContext.Items is a non-thread-safe Hashtable; the crash bottoms out in Hashtable.get_Item). Lock on a stable per-context monitor and re-check inside the lock instead of "return httpContext.GetScope();".
SCOPE: confirmed by decompiling DotNetNuke.dll from a 10.3.2 install; the same recursive retry + "GetScope_lock" key are still present on develop:
https://github.com/dnnsoftware/Dnn.Platform/blob/develop/DNN%20Platform/Library/Common/Extensions/HttpContextDependencyInjectionExtensions.cs
WORKAROUND for operators until fixed: avoid resolving DI-backed services after request scope disposal (e.g. in late EndRequest handlers); reduce concurrent upload requests. (Raising the ASP.NET min thread-pool size makes it worse.)
DIAGNOSED WITH:
dotnet-dump analyze w3wp.exe..dmp -c "clrthreads" -c "syncblk" -c "clrstack -all" -c "exit"
-> thread with System.StackOverflowException has ~5,104 GetScope(HttpContextBase) frames; syncblk empty (not a deadlock).
getscope-stackoverflow-callstack 1.txt
Affected Versions
10.3.3 (latest release)
What browsers are you seeing the problem on?
Chrome
Code of Conduct
Is there an existing issue for this?
What happened?
Under concurrent request load (reliably reproduced with a bulk file upload/overwrite through the Resource Manager / Digital Asset Manager), DotNetNuke.Common.Extensions.HttpContextDependencyInjectionExtensions.GetScope(HttpContextBase) calls itself with no recursion bound and never terminates. The IIS worker process crashes with a StackOverflowException (Windows exception code 0xC00000FD, uncatchable). Repeated crashes trip WAS Rapid-Fail Protection and take the whole application pool offline.
Steps to reproduce?
(This fires many concurrent POST /API/InternalServices/FileUpload/UploadFromLocal requests, multiplexed over one HTTP/2 connection.)
A single-file upload never triggers it; only concurrent bulk uploads do.
Current Behavior
w3wp.exe crashes with exception code 0xC00000FD (STACK_OVERFLOW), faulting module mscorlib.ni.dll. The application pool enters a kill/restart loop (WAS Event 5011 roughly every 90 seconds) and eventually goes offline (503 / AppOffline). Because a StackOverflowException cannot be caught, nothing is logged by the application itself.
Expected Behavior
Concurrent requests that need the per-request DI scope resolve it safely and deterministically, with no unbounded recursion and no process crash.
Relevant log output
Anything else?
ROOT CAUSE (deterministic) — ClearScope/DisposeScope remove the scope entry but leave the "GetScope_lock" sentinel in HttpContext.Items:
GetScope registers AddOnRequestCompleted(DisposeScope). After the request scope is disposed, Items[typeof(IServiceScope)] is gone but Items["GetScope_lock"] remains. Any later GetScope call then hits:
if (httpContext.Items.Contains("GetScope_lock")) return httpContext.GetScope();
and recurses forever -> StackOverflowException. Once GetScope runs after teardown, the crash is guaranteed (not a race).
OBSERVED TRIGGER (faulting-thread stack): a DI-activated service is resolved during an EndRequest module, after scope disposal:
GetScope(HttpContextBase) <- recurses 5,104x
DotNetNuke.Common.Globals.GetCurrentServiceProvider()
DotNetNuke.Entities.Modules.ModuleController..ctor(IEventLogger, IPermissionDefinitionService, IHostSettings)
DotNetNuke.Entities.Modules.ModuleController..ctor()
.ConfigurationController..ctor()
.SiteLogModule.OnEndRequest(object, EventArgs)
Constructing ModuleController via its parameterless ctor (which calls GetCurrentServiceProvider) after the scope is disposed is enough to hit this. Bulk file upload/overwrite reproduces it reliably.
MINIMAL FIX — clear the sentinel in ClearScope:
public static void ClearScope(this HttpContextBase httpContext)
{
httpContext.Items.Remove(typeof(IServiceScope));
httpContext.Items.Remove("GetScope_lock"); // add this
}
ROBUST FIX — also make the retry non-recursive and thread-safe (HttpContext.Items is a non-thread-safe Hashtable; the crash bottoms out in Hashtable.get_Item). Lock on a stable per-context monitor and re-check inside the lock instead of "return httpContext.GetScope();".
SCOPE: confirmed by decompiling DotNetNuke.dll from a 10.3.2 install; the same recursive retry + "GetScope_lock" key are still present on develop:
https://github.com/dnnsoftware/Dnn.Platform/blob/develop/DNN%20Platform/Library/Common/Extensions/HttpContextDependencyInjectionExtensions.cs
WORKAROUND for operators until fixed: avoid resolving DI-backed services after request scope disposal (e.g. in late EndRequest handlers); reduce concurrent upload requests. (Raising the ASP.NET min thread-pool size makes it worse.)
DIAGNOSED WITH:
dotnet-dump analyze w3wp.exe..dmp -c "clrthreads" -c "syncblk" -c "clrstack -all" -c "exit"
-> thread with System.StackOverflowException has ~5,104 GetScope(HttpContextBase) frames; syncblk empty (not a deadlock).
getscope-stackoverflow-callstack 1.txt
Affected Versions
10.3.3 (latest release)
What browsers are you seeing the problem on?
Chrome
Code of Conduct