You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modules-dev@httpd.apache.org by David Wortham <dj...@gmail.com> on 2007/02/07 22:19:26 UTC

Whitescreens when using a dir-conf merge function

Hi all,
   I'm adding a merge function (for use with directory-based configuration
and server-based configuration).

When I finished the function, I noticed that it was causing whitescreens
(empty responses).

As you can see below, I allocate memory via 'apr_pcalloc' and then I:
(1) loop through each existing 'rbl_handler' from the parentdir_cfg, copying
it to the new_dir_cfg, then
(2) loop through each existing 'rbl_handler' from the subdir_cfg, copying it
to the new_dir_cfg.

With my current directive configuration, there are no directives to copy (so
the loops fail the first conditional and are never entered), but Apache
whitescreens nonetheless.  There are no errors or warnings on compile.

Am I allocating memory correctly, or perhaps my concept of merging (and when
the merge function is called) is bad?



The relevant code follows:

/* start code snippet */

// since memcpy was causing errors, I coded this function to do the same
(only much slower)
static void apr_copy_rbhlcpy(apr_pool_t* p, rbl_handler* from_rbl_handler,
rbl_handler* to_rbl_handler)
{
    if (from_rbl_handler)
    {
        to_rbl_handler->category_bs     = from_rbl_handler->category_bs;
        to_rbl_handler->score_lb        = from_rbl_handler->score_lb;
        to_rbl_handler->score_ub        = from_rbl_handler->score_ub;
        to_rbl_handler->days_lb         = from_rbl_handler->days_lb;
        to_rbl_handler->days_ub         = from_rbl_handler->days_ub;
        to_rbl_handler->verb_bs         = from_rbl_handler->verb_bs;
        to_rbl_handler->action_string   =
(from_rbl_handler->action_string)?apr_pstrdup(p,
from_rbl_handler->action_string):NULL;
    }
}

// the merge function
static void* my_merge_dir_conf (apr_pool_t* p, void* parent_dirv, void*
subdirv)
{
    httpbl_dir_cfg* parent_dir              = (httpbl_dir_cfg *)
parent_dirv;
    httpbl_dir_cfg* subdir                  = (httpbl_dir_cfg *) subdirv;
    httpbl_dir_cfg* new_dir_cfg             = (httpbl_dir_cfg *) apr_palloc
(p, sizeof(httpbl_dir_cfg));

    int             i                       = 0; // i = the
num_of_rbl_handlers already written in the new_dir_cfg array
    int             j                       = 0; // j = the
num_of_rbl_handlers read from from_rbl_handler
    new_dir_cfg->default_action             = subdir->default_action;
    new_dir_cfg->is_404_recording_enabled   =
subdir->is_404_recording_enabled;
    new_dir_cfg->is_exempt                  = subdir->is_exempt;
    new_dir_cfg->is_httpbl_enabled          = subdir->is_httpbl_enabled;
    new_dir_cfg->something                  =
(subdir->something)?apr_pstrdup(p, subdir->something):NULL;
    new_dir_cfg->the_rbl_handlers           = (rbl_handler **)apr_pcalloc(
p, (MAX_RBL_DIRECTIVES)*sizeof(rbl_handler*) );
    new_dir_cfg->num_of_rbl_handlers        = 0;

    rbl_handler*    from_rbl_handler;
    rbl_handler*    to_rbl_handler;
    // fill in rbl directives starting with the parent, then the child
(returning an error string if more than MAX_RBL_DIRECTIVES rbl_handlers are
created/attempted
    for (i = 0; i < parent_dir->num_of_rbl_handlers &&
new_dir_cfg->num_of_rbl_handlers <= MAX_RBL_DIRECTIVES; i++)
    {
        from_rbl_handler    = parent_dir->the_rbl_handlers[i];
        to_rbl_handler      = new_dir_cfg->the_rbl_handlers[i];

        if (from_rbl_handler)
        {
            apr_copy_rbhlcpy(p, from_rbl_handler, to_rbl_handler);
//            memcpy(to_rbl_handler, from_rbl_handler, sizeof(rbl_handler));
// try a direct memory copy
            (new_dir_cfg->num_of_rbl_handlers)++;
        }
    }
    for (j = 0; j < subdir->num_of_rbl_handlers &&
new_dir_cfg->num_of_rbl_handlers < MAX_RBL_DIRECTIVES; j++)
    {
        from_rbl_handler    = subdir->the_rbl_handlers[j];
        to_rbl_handler      = new_dir_cfg->the_rbl_handlers[i];

        if (from_rbl_handler)
        {
            apr_copy_rbhlcpy(p, from_rbl_handler, to_rbl_handler);
//            memcpy(to_rbl_handler, from_rbl_handler, sizeof(rbl_handler));
// try a direct memory copy
            (new_dir_cfg->num_of_rbl_handlers)++;
            i++;
        }
    }

    return new_dir_cfg;
}


/* end code snippet */

Dave

Re: Whitescreens when using a dir-conf merge function

Posted by Todd Esposito <to...@toddesposito.com>.
David,

David Wortham wrote:
> As I suspected, the lines causing the segfault are similar to:
>
> // dir_cfg contains mostly ints
> struct intContainer
> {
>    int x
> } intContainer;
>
> /* ... later... in the merge function */
> static void* dir_cfg_merge_function (apr_pool_t* the_pool, void*
> the_parent_dir_cfg, void* the_sub_dir_cfg)
> {
>    intContainer* merged_dir_cfg = apr_pcalloc(p, 1*sizeof(intContainer));
>
>    int y = 1;
The apr_pcalloc call should NOT fail unless you are really really tight 
on memory or you're doing something pathological to that pool.  Unless 
intContainer is unearthly huge (and I doubt it is), this should never 
fail... but, to be on the safe side, how about something like:

if (! (merged_dir_cfg))   // we assume ! NULL == true, safe if not "proper"
  { ap_log_error (....., "couldn't allocate memory for merged_dir_cfg);  }
else {
>    merged_dir_cfg->x = y; // this line causes a segfault... why?
> // this line would also segfault:
>    memcpy(, , 1*sizeof(int));
}
>    return merged_dir_cfg;
> }
- Todd


Re: Whitescreens when using a dir-conf merge function

Posted by Ralf Mattes <rm...@mh-freiburg.de>.
On Wed, 2007-02-07 at 18:16 -0700, David Wortham wrote:
> Thanks Nick for the response.
> 
> I looked up how to use gdb very quickly.  I found out that the segfault is
> happening at the same place I suspected.
> 
> As I suspected, the lines causing the segfault are similar to:
> 

Argh, can you _please_ post the real code? I hate to have to guess
whether errors are errors or just typos ...


> // dir_cfg contains mostly ints
> struct intContainer
> {
>     int x
> } intContainer;
> 
> /* ... later... in the merge function */
> static void* dir_cfg_merge_function (apr_pool_t* the_pool, void*
> the_parent_dir_cfg, void* the_sub_dir_cfg)
> {
>     intContainer* merged_dir_cfg = apr_pcalloc(p, 1*sizeof(intContainer));
> 
Where does 'p' come from? 
>     int y = 1;
>     merged_dir_cfg->x = y; // this line causes a segfault... why?

You never checked the return value of apr_pcalloc ... iff it's null you
trigger a segfault.
(Side note: the headers aren't too clear about the return value in case
of failures ....).
There's a debugging version of apr_pcalloc - that should help you debug
your module.

 HTH Ralf Mattes

> // this line would also segfault:
>     memcpy(, , 1*sizeof(int));
>     return merged_dir_cfg;
> }
> 
> 
> 
> I still can't figure out what the issue is.  Is there any way to tell if the
> apr_pcalloc is failing?
> 
> 
> 
> On 2/7/07, Nick Kew <ni...@webthing.com> wrote:
> >
> >
> > On 8 Feb 2007, at 00:46, David Wortham wrote:
> >
> > >
> > > I am testing on LINUX, and that's where my whitescreens are showing up
> > > (haven't started cross-platform testing yet).  I have encountered
> > > them in
> > > the past and they culprit has always been a segfault.
> > > I suspected a segfault-like error at the end of startup causing the
> > > whitescreens, but I don't yet have a way to verify this.  Also, I
> > > don't know
> > > where in my code the segfault could have occurred (unless the memory
> > > allocation request was denied).
> >
> > Run it with -X under gdb.  Do whatever it is that causes the segfault.
> > Then get a backtrace from gdb.
> >
> > --
> > Nick Kew
> >


Re: Whitescreens when using a dir-conf merge function

Posted by David Wortham <dj...@gmail.com>.
Thanks Nick for the response.

I looked up how to use gdb very quickly.  I found out that the segfault is
happening at the same place I suspected.

As I suspected, the lines causing the segfault are similar to:

// dir_cfg contains mostly ints
struct intContainer
{
    int x
} intContainer;

/* ... later... in the merge function */
static void* dir_cfg_merge_function (apr_pool_t* the_pool, void*
the_parent_dir_cfg, void* the_sub_dir_cfg)
{
    intContainer* merged_dir_cfg = apr_pcalloc(p, 1*sizeof(intContainer));

    int y = 1;
    merged_dir_cfg->x = y; // this line causes a segfault... why?
// this line would also segfault:
    memcpy(, , 1*sizeof(int));
    return merged_dir_cfg;
}



I still can't figure out what the issue is.  Is there any way to tell if the
apr_pcalloc is failing?



On 2/7/07, Nick Kew <ni...@webthing.com> wrote:
>
>
> On 8 Feb 2007, at 00:46, David Wortham wrote:
>
> >
> > I am testing on LINUX, and that's where my whitescreens are showing up
> > (haven't started cross-platform testing yet).  I have encountered
> > them in
> > the past and they culprit has always been a segfault.
> > I suspected a segfault-like error at the end of startup causing the
> > whitescreens, but I don't yet have a way to verify this.  Also, I
> > don't know
> > where in my code the segfault could have occurred (unless the memory
> > allocation request was denied).
>
> Run it with -X under gdb.  Do whatever it is that causes the segfault.
> Then get a backtrace from gdb.
>
> --
> Nick Kew
>

Re: Whitescreens when using a dir-conf merge function

Posted by Nick Kew <ni...@webthing.com>.
On 8 Feb 2007, at 00:46, David Wortham wrote:

>
> I am testing on LINUX, and that's where my whitescreens are showing up
> (haven't started cross-platform testing yet).  I have encountered  
> them in
> the past and they culprit has always been a segfault.
> I suspected a segfault-like error at the end of startup causing the
> whitescreens, but I don't yet have a way to verify this.  Also, I  
> don't know
> where in my code the segfault could have occurred (unless the memory
> allocation request was denied).

Run it with -X under gdb.  Do whatever it is that causes the segfault.
Then get a backtrace from gdb.

-- 
Nick Kew

Re: Whitescreens when using a dir-conf merge function

Posted by David Wortham <dj...@gmail.com>.
Tom,
   Thanks for the response.

   I think I have tracked the whitescreening issue down to mutating the
newly allocated dir_cfg in the merge function, but I can't figure out why
setting memory that has just been allocated would error (perhaps the
apr_pcalloc returned an error and did not retrieve the memory requested?).

My comments to your response follow:

> When I finished the function, I noticed that it was causing whitescreens
> > (empty responses).
> "White screens" in my experience are often caused by the apache process
> segfaulting (though you didn't mention what platform you are on; this is
> unix-ish).


I am testing on LINUX, and that's where my whitescreens are showing up
(haven't started cross-platform testing yet).  I have encountered them in
the past and they culprit has always been a segfault.
I suspected a segfault-like error at the end of startup causing the
whitescreens, but I don't yet have a way to verify this.  Also, I don't know
where in my code the segfault could have occurred (unless the memory
allocation request was denied).

  Have you checked your apache error log to see if this is the
> case?  You also may want to change your LogLevel to "debug" to get the
> most information possible into those logs.


My module is particularly large and I have, therefore, made very extensive
use of logging (many sets of files and structure/memory dumps to both STDERR
and error.log).
Nothing seems to show up in the error log (and nothing [other than my
standard debugging code] shows up in the STDERR console where I startup the
http daemon).
I will do some more testing with more verbose logging later this evening.

> As you can see below, I allocate memory via 'apr_pcalloc' and then I:
> > (1) loop through each existing 'rbl_handler' from the parentdir_cfg,
> > copying
> > it to the new_dir_cfg, then
> > (2) loop through each existing 'rbl_handler' from the subdir_cfg,
> > copying it
> > to the new_dir_cfg.
> A VERY brief look at your code looks like you're moving pointers; you
> may want to consider using apr_pstrdup and/or memcpy instead, unless you
> are SURE the pointers in question are pointing at things which are in a
> long-life pool.


The whitescreens show after either copying integers or 'apr_pstrdup'ing
strings (or both).  A segfault can't occur when setting "int x = (int)y",
can it?  I'm thinking that since the assignment-side is part of a struct
which is in dyn-allocated memory, that is a potential point for the
segfault.
Memcpy also caused the same errors... I have those lines commented out in my
sample code.  Can you think of any reason 'memcpy' would cause a segfault
(or other similar error)?
My assumption is that the pool (the first parameter of the merge function)
should last for the life of the newly created dir_cfg... am I wrong?

HTH,
>
> Todd


Any more ideas?

Thanks,
Dave

Re: Whitescreens when using a dir-conf merge function

Posted by Todd Esposito <to...@toddesposito.com>.
Hi David,

David Wortham wrote:
> Hi all,
>   I'm adding a merge function (for use with directory-based configuration
> and server-based configuration).
>
> When I finished the function, I noticed that it was causing whitescreens
> (empty responses).
"White screens" in my experience are often caused by the apache process 
segfaulting (though you didn't mention what platform you are on; this is 
unix-ish).  Have you checked your apache error log to see if this is the 
case?  You also may want to change your LogLevel to "debug" to get the 
most information possible into those logs.
> As you can see below, I allocate memory via 'apr_pcalloc' and then I:
> (1) loop through each existing 'rbl_handler' from the parentdir_cfg, 
> copying
> it to the new_dir_cfg, then
> (2) loop through each existing 'rbl_handler' from the subdir_cfg, 
> copying it
> to the new_dir_cfg.
A VERY brief look at your code looks like you're moving pointers; you 
may want to consider using apr_pstrdup and/or memcpy instead, unless you 
are SURE the pointers in question are pointing at things which are in a 
long-life pool.

HTH,

Todd


RE: Whitescreens when using a dir-conf merge function

Posted by 张 臻博 <la...@hotmail.com>.
Hi,

I have gone through your code quickly. It seems there is some problem in 
your merge function:
>    rbl_handler*    from_rbl_handler;
>    rbl_handler*    to_rbl_handler;
here you haven't pcalloc the memory for it. However late you pass these 
pointers to the function:
>static void apr_copy_rbhlcpy(apr_pool_t* p, rbl_handler* 
>from_rbl_handler,
>rbl_handler* to_rbl_handler)
In this function you use pointer to accept parmaters. Should you use double 
pointer?(e.g.rbl_handler* from_rbl_handler). My suggestion is that you 
allocate the memory in your merge function and then in apr_copy_rbhlcpy try 
to use double pointer. 

I am not so sure whether it is the reason. but you can have a try.

br
frankie



>From: "David Wortham" <dj...@gmail.com>
>Reply-To: modules-dev@httpd.apache.org
>To: modules-dev@httpd.apache.org
>Subject: Whitescreens when using a dir-conf merge function
>Date: Wed, 7 Feb 2007 14:19:26 -0700
>
>Hi all,
>   I'm adding a merge function (for use with directory-based 
>configuration
>and server-based configuration).
>
>When I finished the function, I noticed that it was causing 
>whitescreens
>(empty responses).
>
>As you can see below, I allocate memory via 'apr_pcalloc' and then 
>I:
>(1) loop through each existing 'rbl_handler' from the parentdir_cfg, 
>copying
>it to the new_dir_cfg, then
>(2) loop through each existing 'rbl_handler' from the subdir_cfg, 
>copying it
>to the new_dir_cfg.
>
>With my current directive configuration, there are no directives to 
>copy (so
>the loops fail the first conditional and are never entered), but 
>Apache
>whitescreens nonetheless.  There are no errors or warnings on 
>compile.
>
>Am I allocating memory correctly, or perhaps my concept of merging 
>(and when
>the merge function is called) is bad?
>
>
>
>The relevant code follows:
>
>/* start code snippet */
>
>// since memcpy was causing errors, I coded this function to do the 
>same
>(only much slower)
>static void apr_copy_rbhlcpy(apr_pool_t* p, rbl_handler* 
>from_rbl_handler,
>rbl_handler* to_rbl_handler)
>{
>    if (from_rbl_handler)
>    {
>        to_rbl_handler->category_bs     = 
>from_rbl_handler->category_bs;
>        to_rbl_handler->score_lb        = 
>from_rbl_handler->score_lb;
>        to_rbl_handler->score_ub        = 
>from_rbl_handler->score_ub;
>        to_rbl_handler->days_lb         = from_rbl_handler->days_lb;
>        to_rbl_handler->days_ub         = from_rbl_handler->days_ub;
>        to_rbl_handler->verb_bs         = from_rbl_handler->verb_bs;
>        to_rbl_handler->action_string   =
>(from_rbl_handler->action_string)?apr_pstrdup(p,
>from_rbl_handler->action_string):NULL;
>    }
>}
>
>// the merge function
>static void* my_merge_dir_conf (apr_pool_t* p, void* parent_dirv, 
>void*
>subdirv)
>{
>    httpbl_dir_cfg* parent_dir              = (httpbl_dir_cfg *)
>parent_dirv;
>    httpbl_dir_cfg* subdir                  = (httpbl_dir_cfg *) 
>subdirv;
>    httpbl_dir_cfg* new_dir_cfg             = (httpbl_dir_cfg *) 
>apr_palloc
>(p, sizeof(httpbl_dir_cfg));
>
>    int             i                       = 0; // i = the
>num_of_rbl_handlers already written in the new_dir_cfg array
>    int             j                       = 0; // j = the
>num_of_rbl_handlers read from from_rbl_handler
>    new_dir_cfg->default_action             = 
>subdir->default_action;
>    new_dir_cfg->is_404_recording_enabled   =
>subdir->is_404_recording_enabled;
>    new_dir_cfg->is_exempt                  = subdir->is_exempt;
>    new_dir_cfg->is_httpbl_enabled          = 
>subdir->is_httpbl_enabled;
>    new_dir_cfg->something                  =
>(subdir->something)?apr_pstrdup(p, subdir->something):NULL;
>    new_dir_cfg->the_rbl_handlers           = (rbl_handler 
>**)apr_pcalloc(
>p, (MAX_RBL_DIRECTIVES)*sizeof(rbl_handler*) );
>    new_dir_cfg->num_of_rbl_handlers        = 0;
>
>    rbl_handler*    from_rbl_handler;
>    rbl_handler*    to_rbl_handler;
>    // fill in rbl directives starting with the parent, then the 
>child
>(returning an error string if more than MAX_RBL_DIRECTIVES 
>rbl_handlers are
>created/attempted
>    for (i = 0; i < parent_dir->num_of_rbl_handlers &&
>new_dir_cfg->num_of_rbl_handlers <= MAX_RBL_DIRECTIVES; i++)
>    {
>        from_rbl_handler    = parent_dir->the_rbl_handlers[i];
>        to_rbl_handler      = new_dir_cfg->the_rbl_handlers[i];
>
>        if (from_rbl_handler)
>        {
>            apr_copy_rbhlcpy(p, from_rbl_handler, to_rbl_handler);
>//            memcpy(to_rbl_handler, from_rbl_handler, 
>sizeof(rbl_handler));
>// try a direct memory copy
>            (new_dir_cfg->num_of_rbl_handlers)++;
>        }
>    }
>    for (j = 0; j < subdir->num_of_rbl_handlers &&
>new_dir_cfg->num_of_rbl_handlers < MAX_RBL_DIRECTIVES; j++)
>    {
>        from_rbl_handler    = subdir->the_rbl_handlers[j];
>        to_rbl_handler      = new_dir_cfg->the_rbl_handlers[i];
>
>        if (from_rbl_handler)
>        {
>            apr_copy_rbhlcpy(p, from_rbl_handler, to_rbl_handler);
>//            memcpy(to_rbl_handler, from_rbl_handler, 
>sizeof(rbl_handler));
>// try a direct memory copy
>            (new_dir_cfg->num_of_rbl_handlers)++;
>            i++;
>        }
>    }
>
>    return new_dir_cfg;
>}
>
>
>/* end code snippet */
>
>Dave

_________________________________________________________________
与联机的朋友进行交流,请使用 Live Messenger; 
http://get.live.com/messenger/overview