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