Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Error ExceptionMiddleware #4498

Closed
leigh-pointer opened this issue Aug 9, 2024 · 4 comments
Closed

[BUG] Error ExceptionMiddleware #4498

leigh-pointer opened this issue Aug 9, 2024 · 4 comments

Comments

@leigh-pointer
Copy link
Contributor

Oqtane Info

Version - 5.2.0
Render Mode - interactive
Interactivity - Server
Database - SQL Server

Describe the bug

Receive a lot of error log emails but seems intermittent.

The log:
image

The exception

System.ArgumentException: Destination array was not long enough. Check the destination index, length, and the array's lower bounds. (Parameter 'destinationArray')
   at System.Array.CopyImpl(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
   at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length)
   at System.Collections.Generic.List`1.Insert(Int32 index, T item)
   at Oqtane.Repository.ModuleDefinitionRepository.ProcessModuleDefinitions(Int32 siteId) in C:\Source\Projects\oqtane.framework\Oqtane.Server\Repository\ModuleDefinitionRepository.cs:line 224
   at Oqtane.Repository.ModuleDefinitionRepository.<>c__DisplayClass14_0.<LoadModuleDefinitions>b__0(ICacheEntry entry) in C:\Source\Projects\oqtane.framework\Oqtane.Server\Repository\ModuleDefinitionRepository.cs:line 118
   at Microsoft.Extensions.Caching.Memory.CacheExtensions.GetOrCreate[TItem](IMemoryCache cache, Object key, Func`2 factory)
   at Oqtane.Repository.ModuleDefinitionRepository.LoadModuleDefinitions(Int32 siteId) in C:\Source\Projects\oqtane.framework\Oqtane.Server\Repository\ModuleDefinitionRepository.cs:line 115
   at Oqtane.Repository.ModuleDefinitionRepository.GetModuleDefinitions(Int32 siteId) in C:\Source\Projects\oqtane.framework\Oqtane.Server\Repository\ModuleDefinitionRepository.cs:line 43
   at Oqtane.Repository.SiteRepository.InitializeSite(Alias alias) in C:\Source\Projects\oqtane.framework\Oqtane.Server\Repository\SiteRepository.cs:line 174
   at Oqtane.Infrastructure.TenantMiddleware.Invoke(HttpContext context) in C:\Source\Projects\oqtane.framework\Oqtane.Server\Infrastructure\Middleware\TenantMiddleware.cs:line 56
   at Oqtane.Infrastructure.ExceptionMiddleware.Invoke(HttpContext context, IServiceProvider provider) in C:\Source\Projects\oqtane.framework\Oqtane.Server\Infrastructure\Middleware\ExceptionMiddleware.cs:line 25

@sbwalker
Copy link
Member

sbwalker commented Aug 9, 2024

I am not sure how to reproduce this issue. The Oqtane line of code with the exception is line 224 in ModuleDefinitionRepository.cs:

serverState.Assemblies.Insert(0, assembly.Trim());

which is basically adding any Dependencies which have been defined in the IModule interface to a List which can be used when running on WebAssembly so that it knows which DLLs need to be downloaded to the client browser. I am not sure how adding an item to a standard List can result in "Destination array was not long enough"?

Do you have custom modules where you are defining Dependencies? Is this only happening in development, or also in production? Are you able to put a breakpoint on this line of code to determine which assembly is triggering the error?

@zyhfish
Copy link
Contributor

zyhfish commented Aug 12, 2024

this maybe a race condition issue that the ProcessModuleDefinitions called in the same time, but the code is not thread safe.

@sbwalker
Copy link
Member

@zyhfish the TenantMiddleware has the following logic to handle the first request to a site:

                    // handle first request to site
                    var serverState = context.RequestServices.GetService(typeof(IServerStateManager)) as IServerStateManager;
                    if (!serverState.GetServerState(alias.SiteKey).IsInitialized)
                    {
                        var sites = context.RequestServices.GetService(typeof(ISiteRepository)) as ISiteRepository;
                        sites.InitializeSite(alias);
                    }

and InitializeSite uses a lock to ensure the logic is only executed once:

        public void InitializeSite(Alias alias)
        {
            var serverstate = _serverState.GetServerState(alias.SiteKey);
            if (!serverstate.IsInitialized)
            {
                // ensure site initialization is only executed once
                lock (_lock)
                {
                    if (!serverstate.IsInitialized)
                    {
                        var site = GetSite(alias.SiteId);
                        if (site != null)
                        {
                            // initialize theme Assemblies
                            site.Themes = _themeRepository.GetThemes().ToList();

                            // initialize module Assemblies
                            var moduleDefinitions = _moduleDefinitionRepository.GetModuleDefinitions(alias.SiteId);

this is where the module assemblies list is initialized.

@zyhfish
Copy link
Contributor

zyhfish commented Aug 12, 2024

Hi @sbwalker ,
the LoadModuleDefinitions function can also be triggered from other places, such as from a background job, maybe this will cause a race condition issue.

sbwalker added a commit that referenced this issue Aug 20, 2024
fix #4498 build ServerState Assemblies collection in a more thread safe manner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants