[syslog-ng] [PATCH 7/7] [logreader]: Proper wakeup function handling

Balazs Scheidler bazsi at balabit.hu
Thu Jun 9 14:55:46 CEST 2011


Hi,

I've changed this patch almost completely, but the diagnosis of the
possible bug was right, I just think I've found a simpler
implementation.

Here's the patch:

commit 694164b1ea6f575424413b3b1f359af09457db16
Author: Balazs Scheidler <bazsi at balabit.hu>
Date:   Thu Jun 9 14:54:07 2011 +0200

    LogReader: Proper wakeup function handling for deinitialized LogReaders
    
    The wakeup() callback can be called even if a LogReader is
    deinitialized (when the Writer is deinitialized _after_ the reader, and
    some messages are flushed out in the deinit path), in
    which case we shouldn't trigger the schedule_wakeup event.
    
    The original patch by Viktor Juhasz, but was completely
    reworked by Balazs Scheidler.
    
    Signed-off-by: Viktor Juhasz <jviktor at balabit.hu>
    Signed-off-by: Balazs Scheidler <bazsi at balabit.hu>


On Mon, 2011-05-23 at 11:56 +0200, Gergely Nagy wrote:
> From: Juhasz Viktor <jviktor at balabit.hu>
> 
> Rearrange how self->super.wakeup is handled, in order to stop a race
> condition where it might be called earlier than it is set, or after it
> should have been cleared.
> 
> If the reader is uninitialized, but the writer tries to flush the
> queue, and call log_msg_refcache_stop(), that in turn will call the
> reader's wakeup function. Since the reader is uninitialized, this can
> easily corrupt the ivykis event list.
> 
> To avoid this scenario, the wakeup callback should be set differently,
> and cleared early.
> 
> Signed-off-by: Viktor Juhasz <jviktor at balabit.hu>
> ---
>  lib/logreader.c |   16 ++++++++++++----
>  1 files changed, 12 insertions(+), 4 deletions(-)
> 
> diff --git a/lib/logreader.c b/lib/logreader.c
> index 268be6e..4e56d05 100644
> --- a/lib/logreader.c
> +++ b/lib/logreader.c
> @@ -577,7 +577,8 @@ static gboolean
>  log_reader_init(LogPipe *s)
>  {
>    LogReader *self = (LogReader *) s;
> -
> +  /* If reader is initialized than log_msg_ref_cache_stop can call the wakeup function */
> +  self->super.wakeup = log_reader_wakeup;
>    if (!log_source_init(s))
>      return FALSE;
>    /* check for new data */
> @@ -612,7 +613,6 @@ log_reader_init(LogPipe *s)
>    if (!log_reader_start_watches(self))
>      return FALSE;
>    iv_event_register(&self->schedule_wakeup);
> -
>    return TRUE;
>  }
>  
> @@ -622,7 +622,14 @@ log_reader_deinit(LogPipe *s)
>    LogReader *self = (LogReader *) s;
>    
>    main_loop_assert_main_thread();
> -
> +  /*
> +    the wakeup function must be set to NULL, because it can be occured than
> +    the reader is uninitialized but the writer flush the queue and call the log_msg_refcache_stop and
> +    log_msg_refcache_stop call the wakeup function if it is not null, but in this case the reader
> +    is uninitialized and the call of iv_event_post for the unregistered event can cause an ivykis list corruption.
> +    IF logreader is uninitialized than the wakeup function is NULL so the iv_event_post isn't called.
> +  */
> +  self->super.wakeup = NULL;
>    iv_event_unregister(&self->schedule_wakeup);
>    log_reader_stop_watches(self);
>    if (!log_source_deinit(s))
> @@ -684,7 +691,8 @@ log_reader_new(LogProto *proto)
>    self->super.super.init = log_reader_init;
>    self->super.super.deinit = log_reader_deinit;
>    self->super.super.free_fn = log_reader_free;
> -  self->super.wakeup = log_reader_wakeup;
> +  /* Set wakeup function to NULL because this is set in the log_reader_init and unset in the log_reader_deinit */
> +  self->super.wakeup = NULL;
>    self->proto = proto;
>    self->immediate_check = FALSE;
>    self->pollable_state = -1;

-- 
Bazsi




More information about the syslog-ng mailing list