Matt Grimwade created LOG4NET-646:
-------------------------------------

             Summary: 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


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