stas 2003/08/20 19:11:30
Modified: xs/APR/APR APR.xs Added: t/apr-ext perlio.t Log: APR::PerlIO needs optional functions which require apr_hook_global_pool to be initialized. unfortunately APR_initialize() doesn't do that (httpd does it manually). fix it for the outside-modperl usages, during the APR.xs boot Revision Changes Path 1.6 +24 -0 modperl-2.0/xs/APR/APR/APR.xs Index: APR.xs =================================================================== RCS file: /home/cvs/modperl-2.0/xs/APR/APR/APR.xs,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- APR.xs 26 Nov 2002 17:09:03 -0000 1.5 +++ APR.xs 21 Aug 2003 02:11:30 -0000 1.6 @@ -8,6 +8,29 @@ # define APR_terminate() #endif +#ifdef MP_HAVE_APR_LIBS + +/* XXX: APR_initialize doesn't initialize apr_hook_global_pool, needed for + * work outside httpd, so do it manually PR22605 */ +#include "apr_hooks.h" +static void extra_apr_init(void) +{ + if (apr_hook_global_pool == NULL) { + apr_pool_t *global_pool; + apr_status_t rv = apr_pool_create(&global_pool, NULL); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, + "Fatal error: unable to create global pool " + "for use with by the scoreboard"); + } + /* XXX: mutex locking? */ + apr_hook_global_pool = global_pool; + } +} +#else +# define extra_apr_init() +#endif + MODULE = APR PACKAGE = APR PROTOTYPES: disable @@ -15,6 +38,7 @@ BOOT: file = file; /* -Wall */ APR_initialize(); + extra_apr_init(); void END() 1.1 modperl-2.0/t/apr-ext/perlio.t Index: perlio.t =================================================================== use strict; use warnings FATAL => 'all'; # XXX: this is pretty much the same test as # t/response/TestAPR/perlio.pm, but used outside mod_perl # consider # avoiding the code duplication. use blib; use Apache2; use Apache::Test; use Apache::TestUtil; use Apache::Build (); use Fcntl (); use File::Spec::Functions qw(catfile); #XXX: APR::LARGE_FILES_CONFLICT constant? #XXX: you can set to zero if largefile support is not enabled in Perl use constant LARGE_FILES_CONFLICT => 1; my $build = Apache::Build->build_config; # XXX: only when apr-config is found APR will be linked against # libapr/libaprutil, probably need a more intuitive method for this # prerequisite # also need to check whether we build against the source tree, in # which case we APR.so won't be linked against libapr/libaprutil my $has_apr_config = $build->{apr_config_path} && !$build->httpd_is_source_tree; my $tests = 11; my $lfs_tests = 3; $tests += $lfs_tests unless LARGE_FILES_CONFLICT; plan tests => $tests, have {"the build couldn't find apr-config" => $has_apr_config, "This Perl build doesn't support PerlIO layers" => (eval { require APR; require APR::PerlIO } && APR::PerlIO::PERLIO_LAYERS_ARE_ENABLED()), }; require APR::Pool; my $pool = APR::Pool->new(); my $vars = Apache::Test::config()->{vars}; my $dir = catfile $vars->{documentroot}, "perlio-ext"; t_mkdir($dir); my $sep = "-- sep --\n"; my @lines = ("This is a test: $$\n", "test line --sep two\n"); my $expected = $lines[0]; my $expected_all = join $sep, @lines; # write file my $file = catfile $dir, "test"; t_debug "open file $file for writing"; my $foo = "bar"; open my $fh, ">:APR", $file, $pool or die "Cannot open $file for writing: $!"; ok ref($fh) eq 'GLOB'; t_debug "write to a file:\n$expected\n"; print $fh $expected_all; close $fh; # open() failure test { # workaround for locale setups where the error message may be # in a different language open my $fh, "perlio_this_file_cannot_exist"; my $errno_string = "$!"; # non-existent file my $file = "/this/file/does/not/exist"; if (open my $fh, "<:APR", $file, $pool) { t_debug "must not be able to open $file!"; ok 0; close $fh; } else { ok t_cmp($errno_string, "$!", "expected failure"); } } # seek/tell() tests unless (LARGE_FILES_CONFLICT) { open my $fh, "<:APR", $file, $pool or die "Cannot open $file for reading: $!"; # read the whole file so we can test the buffer flushed # correctly on seek. my $dummy = join '', <$fh>; # Fcntl::SEEK_SET() my $pos = 3; # rewinds after reading 6 chars above seek $fh, $pos, Fcntl::SEEK_SET(); my $got = tell($fh); ok t_cmp($pos, $got, "seek/tell the file Fcntl::SEEK_SET"); # Fcntl::SEEK_CUR() my $step = 10; $pos = tell($fh) + $step; seek $fh, $step, Fcntl::SEEK_CUR(); $got = tell($fh); ok t_cmp($pos, $got, "seek/tell the file Fcntl::SEEK_CUR"); # Fcntl::SEEK_END() $pos = -s $file; seek $fh, 0, Fcntl::SEEK_END(); $got = tell($fh); ok t_cmp($pos, $got, "seek/tell the file Fcntl::SEEK_END"); close $fh; } # read() tests { open my $fh, "<:APR", $file, $pool or die "Cannot open $file for reading: $!"; # basic open test ok ref($fh) eq 'GLOB'; # basic single line read ok t_cmp($expected, scalar(<$fh>), "single line read"); # slurp mode seek $fh, 0, Fcntl::SEEK_SET(); # rewind to the start local $/; #XXX: does not work with current release of httpd (2.0.39) # ok t_cmp($expected_all, # scalar(<$fh>), # "slurp file"); # test ungetc (a long sep requires read ahead) seek $fh, 0, Fcntl::SEEK_SET(); # rewind to the start local $/ = $sep; my @got_lines = <$fh>; my @expect = ($lines[0] . $sep, $lines[1]); ok t_cmp([EMAIL PROTECTED], [EMAIL PROTECTED], "custom complex input record sep read"); close $fh; } # eof() tests { open my $fh, "<:APR", $file, $pool or die "Cannot open $file for reading: $!"; ok t_cmp(0, int eof($fh), # returns false, not 0 "not end of file"); # go to the end and read so eof will return 1 seek $fh, 0, Fcntl::SEEK_END(); my $received = <$fh>; t_debug($received); ok t_cmp(1, eof($fh), "end of file"); close $fh; } # dup() test { open my $fh, "<:APR", $file, $pool or die "Cannot open $file for reading: $!"; open my $dup_fh, "<&:APR", $fh or die "Cannot dup $file for reading: $!"; close $fh; ok ref($dup_fh) eq 'GLOB'; my $received = <$dup_fh>; close $dup_fh; ok t_cmp($expected, $received, "read/write a dupped file"); } # unbuffered write { open my $wfh, ">:APR", $file, $pool or die "Cannot open $file for writing: $!"; open my $rfh, "<:APR", $file, $pool or die "Cannot open $file for reading: $!"; my $expected = "This is an un buffering write test"; # unbuffer my $oldfh = select($wfh); $| = 1; select($oldfh); print $wfh $expected; # must be flushed to disk immediately ok t_cmp($expected, scalar(<$rfh>), "file unbuffered write"); # buffer up $oldfh = select($wfh); $| = 0; select($oldfh); print $wfh $expected; # should be buffered up and not flushed ok t_cmp(undef, scalar(<$rfh>), "file buffered write"); close $wfh; close $rfh; } # XXX: need tests # - for stdin/out/err as they are handled specially # XXX: tmpfile is missing: # consider to use 5.8's syntax: # open $fh, "+>", undef; # cleanup: t_mkdir will remove the whole tree including the file