You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by David Harris <dh...@drh.net> on 2002/12/20 18:54:32 UTC

[mp1] strange build problem with request_rec structure breaks API

Hi,

I have a most interesting problem. It seems as though mod_perl breaks
API compatibility for apache by modifying the layout of the request_rec
structure.

Let me explain....

I maintain my own Red-Hat-based distribution of linux for my own
internal use -- I take packages from Red Hat and modify them to my
specifications. RPM makes deployment to multiple servers so much easier.

I've modified the Red Hat apache RPM to build two copies of apache: one
with mod_perl statically linked (apache-mod_perl) and the other without
mod_perl (apache-vanilla). Both builds have EAPI from mod_ssl patched
in. (However mod_ssl is built separately; see below.)

These two apache builds start with the same source tree. I copy this
source tree and then run configure and make separately in both trees.
The only build difference between apache-vanilla and apache-mod_perl is
two arguments on the configure script:

 "--activate-module=src/modules/perl/libperl.a" \
 "--libexecdir=/usr/lib/apache/modperl" \

And, of course, before I run configure, I let mod_perl hack away at the
apache tree as follows:

CFLAGS="$RPM_OPT_FLAGS" \
perl Makefile.PL \
    PREFIX=$RPM_BUILD_ROOT/usr INSTALLDIRS=vendor \
    APACHE_SRC=`pwd`/../src \
    DO_HTTPD=1 \
    USE_APACI=1 \
    PREP_HTTPD=1 \
    EVERYTHING=1

Everything else is *exactly* the same.

After I have built apache-vanilla and apache-mod_perl, I rebuild the Red
Hat mod_ssl RPM. Mod_ssl builds using apxs installed by the
apache-vanilla RPM -- this apxs came from the build of apache-vanilla
and NOT apache-mod_perl. The apxs from the apache-mod_perl build is
never installed or used anywhere.

Now here is the important part...

I then use this one mod_ssl module (built with apxs from apache-vanilla)
with BOTH apache-vanilla AND apache-mod_perl installations: even though
it technically isn't fully matched with apache-mod_perl (because it was
built using the apxs from apache-vanilla).

This has worked great in the past. The abstraction caused by the API has
made everything work perfectly.

This worked great with:
mod_perl-1.26
apache-1.3.22	(from RH 7.2 distribution)
mod_ssl-2.8.5	(from RH 7.2 distribution)
perl-5.6.0	(from RH 7.2 distribution)

Now, I've upgraded to:
mod_perl-1.27
apache-1.3.27	(from RH 7.3 distribution; rebuilt in 7.2)
mod_ssl-2.8.12	(from RH 7.3 distribution; rebuilt in 7.2)
perl-5.8.0	(from RH 8.0 distribution; rebuilt in 7.2)

And this breaks! When I use apache-mod_perl and mod_ssl together I get a
SEGFAULT. Apache-mod_perl runs fine without mod_ssl. And mod_ssl works
fine with apache-vanilla.

(The upgrade of apache and mod_ssl did not cause this problem. I first
had problems with the older apache and mod_ssl and the newer perl and
mod_perl versions. I upgraded to the latest apache and mod_ssl to try
and fix things before sending this problem report.)

I've used GDB and tracked down why this happens.

The problem is that apache-mod_perl and mod_ssl have different ideas of
the offset of r->ctx inside the request_rec structure. (r is, of course,
a pointer to a request_rec structure).

In GDB I've proved this to myself by evaluating "((void*)&(r->ctx)) -
((void*)r)":

   evaluates to 348 in apache-vanilla
   evaluates to 356 in apache-mod_perl
   evaluates to 348 in mod_ssl

I've tracked the difference down as to where it is in the structure: all
elements before and including "finfo" (type: struct stat) are in sync,
and all elements after and including "parsed_uri" (type: uri_components)
are 8 bytes off (extra 8 bytes in apache-mod_perl).

Either "finfo" is eight bytes longer in apache-mod_perl, or
apache-mod_perl has slipped some other element between "finfo" and
"parsed_uri".

Somehow apache-mod_perl and apache-vanilla have a different ideas of the
request_rec structure. Because I compile mod_ssl using apxs from
apache-vanilla it works with apace-vanilla but not apache-mod_perl.

I suppose you could say that I *should* build mod_ssl using the apxs
from apache-mod_perl if I'm going to use it with apache-mod_perl. I
thought that mod_perl didn't patch the internals of apache to the point
of changing the API.

If this is expected behavior and mod_perl totally breaks the API by
redefining the structures, I would suggest that the MODULE_MAGIC_NUMBER
be updated by mod_perl, so that incompatible modules are not linked
together.

If this is not normal, please help me fix this. I'd love to not have to
maintain two builds of every other module I want to use.

Any other information I can provide, please let me know!

Thanks!

David Harris
President, DRH Internet Inc.
dharris@drh.net
http://www.drh.net/



Re: [mp1] strange build problem with request_rec structure breaks API

Posted by Stas Bekman <st...@stason.org>.
[...]
> I've tracked the difference down as to where it is in the structure: all
> elements before and including "finfo" (type: struct stat) are in sync,
> and all elements after and including "parsed_uri" (type: uri_components)
> are 8 bytes off (extra 8 bytes in apache-mod_perl).
> 
> Either "finfo" is eight bytes longer in apache-mod_perl, or
> apache-mod_perl has slipped some other element between "finfo" and
> "parsed_uri".
> 
> Somehow apache-mod_perl and apache-vanilla have a different ideas of the
> request_rec structure. Because I compile mod_ssl using apxs from
> apache-vanilla it works with apace-vanilla but not apache-mod_perl.

it's the struct stat that's different, not the request_rec. And no, 
mod_perl doesn't mangle the Apache datastructures.

Check this out:

/* sizeof.c */
#include <stdio.h>
#include <sys/stat.h>

int main()
{
     printf("size of struct stat is: %d\n", sizeof(struct stat));
     return 0;
}

# sizeof.pl
use Inline C;

foo();

__END__
__C__
////
int foo()
{
     printf("size of struct stat is: %d\n", sizeof(struct stat));
     return 0;
}


% gcc -o sizeof sizeof.c ; ./sizeof
size of struct stat is: 88

% /home/stas/perl/5.6.0/bin/perl ./sizeof.pl
size of struct stat is: 96

tested with other perls on the same machine and the result is the same 
(beware to delete _Inline before each try, since it won't recompile the 
code if you use a different perl version, but the C code haven't changed)

So as you can see there is indeed 8 bytes difference. This is because 
some of the members of the struct stat aren't of the same size when 
compiled with perl and C. You may want to dig deeper and figure out the 
one that's different. But first compare perl -V of the older perl build 
under which things worked and the output of the newly built perl. I 
suspect that the latter has the USE_LARGE_FILES enabled, whereas the 
older doesn't. On my machine /usr/include/bits/stat.h uses a different 
struct stat when large files are enabled.

Ah, indeed that seems to be the issue:

gcc -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -o sizeof sizeof.c ; ./sizeof
size of struct stat is: 96

here you go -D_FILE_OFFSET_BITS=64 is the one that causes the prob.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com