[logback-dev] Question: AsyncAppender's thread safety?

Aaron Curley accwebs at gmail.com
Fri Mar 4 02:57:39 UTC 2016


Hi Ceki,

Thanks for your responses.  Absolutely; I'll create a JIRA shortly.

As to your question about a test case, I'll see if I can get something 
working over the next 1-2 days.  Unfortunately, even if I am successful, 
the test case is likely to only sometimes detect this particular problem 
(since threads are generally not deterministic).

The performance questions (i.e. the costs of volatile) are a bit harder 
to answer and I'm not sure I'm presently equipped to execute the 
necessary performance testing.  I'll give this more thought.

Aaron



On 3/3/2016 3:13 AM, Ceki Gulcu wrote:
>
> Hi again,
>
> Would you please create a JIRA issue for the problem you raised on the 
> mailing list?
>
> -- 
> Ceki
>
> On 3/3/2016 9:16, Ceki Gulcu wrote:
>> Hi Aaron,
>>
>> Comments inline.
>>
>> On 3/2/2016 23:40, Aaron Curley wrote:
>>
>>  > Hello all,
>>  >
>>  > I’m most likely missing something here, but reviewing 
>> AsyncAppender in
>>  > logback classic 1.1.6, I’m not sure how it’s entirely thread safe,
>>  > especially with respect to the “started” flag in its grandparent
>>  > class (UnsynchronizedAppenderBase).
>>  >
>>  > In particular, the doAppend() method in UnsynchronizedAppenderBase
>>  > checks the “started” boolean member's value (line 72) before
>>  > actually appending, yet, no synchronization primitives are (or appear
>>  > to be, from my perspective) used to ensure that the “started”
>>  > member is visible to all threads once it is updated via start().  I
>>  > would have thought that AsyncAppender would have inherited from
>>  > AppenderBase (which is thread safe and does mark “started” as
>>  > volatile) rather than extending UnsynchronizedAppenderBase.  Baring
>>  > this, I would have thought that the “started” member would be
>>  > “overridden” with AsyncAppender’s own volatile version of this
>>  > flag or access to started would be protected with a lock.
>>  >
>>  > As a result, isn’t it possible that if one thread calls start() and
>>  > then another thread immediately logs something (calling doAppend()),
>>  > the logging thread would see “started” as false?  Wouldn’t this
>>  > result in “skipping” certain log messages entirely (if the
>>  > appender was very recently started)?
>>
>> You are absolutely right. Events generated in other threads could be
>> lost until the new value (true) of start was propagated to those
>> threads. Good catch.
>>
>>  > I think I must be missing something.  Can someone clarify how this
>>  > works?  Thanks in advance!
>>  >
>>  > Best Regards,
>>  >
>>  > Aaron Curley
>>  > accwebs at gmail.com
>>  >
>>  > P. S.  I would have also expected start() and stop() (in
>>  > AsyncAppender or its parent) to be overridden to introduce
>>  > synchronization, since AsyncAppender is generally used by multiple
>>  > threads.  Right now, it appears that start & stop operations are not
>>  > idempotent nor are multiple (simultaneous) calls prevented.
>>
>> The idempotency could be enforced by introducing a check if(isStarted())
>> {return;} at the top of the start() method. But again, good catch.
>>
>> Here are a couple of questions for you.
>>
>> 1) How would you write a test case for asserting the correct propagation
>> of start?
>> 2) What would be the computational cost of having a volatile start?
>> 3) What would you suggest to minimize the cost if the cost was elevated?
>>
>> Best regards,
>>
>> -- 
>> Ceki
>>
>> _______________________________________________
>> logback-dev mailing list
>> logback-dev at qos.ch
>> http://mailman.qos.ch/mailman/listinfo/logback-dev
> _______________________________________________
> logback-dev mailing list
> logback-dev at qos.ch
> http://mailman.qos.ch/mailman/listinfo/logback-dev



More information about the logback-dev mailing list