You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Davyd McColl (Jira)" <ji...@apache.org> on 2020/09/29 06:55:00 UTC

[jira] [Assigned] (LOG4NET-646) RendererMap not threadsafe (IndexOutOfRangeException)

     [ https://issues.apache.org/jira/browse/LOG4NET-646?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Davyd McColl reassigned LOG4NET-646:
------------------------------------

    Assignee: Davyd McColl

> RendererMap not threadsafe (IndexOutOfRangeException)
> -----------------------------------------------------
>
>                 Key: LOG4NET-646
>                 URL: https://issues.apache.org/jira/browse/LOG4NET-646
>             Project: Log4net
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 2.0.8
>            Reporter: Matt Grimwade
>            Assignee: Davyd McColl
>            Priority: Critical
>
> Concurrent calls to code such as
> {code}
> loggerRepository.RendererMap.FindAndRender(new { Foo = "bar" });
> {code}
> occasionally fail with
> {code}
> System.IndexOutOfRangeException: Index was outside the bounds of the array.
>     at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
>     at log4net.ObjectRenderer.RendererMap.Get(Type type)
>     at log4net.ObjectRenderer.RendererMap.FindAndRender(Object obj, TextWriter writer)
> {code}
> Once this has occured, further calls to RendererMap throw. This causes total failure of the logging system.
> This appears to be because log4net.ObjectRenderer.RendererMap is not thread-safe. Internally it holds two Hashtables, {{m_map}} and {{m_cache}}. The first uses a synchronized wrapper and the second does not.
> From https://docs.microsoft.com/en-us/dotnet/api/system.collections.hashtable?view=netframework-4.8:
> {quote}
> Hashtable is thread safe for use by multiple reader threads and a single writing thread. It is thread safe for multi-thread use when only one of the threads perform write (update) operations, which allows for lock-free reads provided that the writers are serialized to the Hashtable. To support multiple writers all operations on the Hashtable must be done through the wrapper returned by the Synchronized(Hashtable) method, provided that there are no threads reading the Hashtable object.
> {quote}
> So when two threads attempt to mutate the cache concurrently its internal state is corrupted.
> A solution (at least for .NET Framework 4.0 onwards) might be to replace both with a ConcurrentDictionary<Type, IObjectRenderer> accessed via its GetOrAdd method.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)