[ 
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)

Reply via email to