You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl-cvs@perl.apache.org by au...@apache.org on 2006/07/05 20:04:30 UTC

svn commit: r419300 - in /perl/Apache-SizeLimit/trunk: lib/Apache/SizeLimit.pm t/response/TestApache/basic.pm t/response/TestApache/deprecated.pm

Author: autarch
Date: Wed Jul  5 11:04:30 2006
New Revision: 419300

URL: http://svn.apache.org/viewvc?rev=419300&view=rev
Log:
Lots of work on the core code, docs, and tests.

* Added a new OO API for configuring Apache::SizeLimit with better
(IMO) names for the methods, such as
Apache::SizeLimit->set_max_process_size().

* Added a new method Apache::SizeLimit->add_cleanup_handler().

* Lots of code refactoring to make the module more testable.

* Docs for all the new bits, plus re-ordering of existing docs to put
the API first, then platform stuff, then other bits.

* Tests for the new and deprecated APIs which actually test something
useful :)

* Basically un-documented the $USE_SMAPS global, except for a
reference in the "DEPRECATED APIS" section. Encouraging people to
explicitly tell the module to use bad data is not a good idea. Based
on discussion with Perrin.

Added:
    perl/Apache-SizeLimit/trunk/t/response/TestApache/deprecated.pm
Modified:
    perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.pm
    perl/Apache-SizeLimit/trunk/t/response/TestApache/basic.pm

Modified: perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.pm
URL: http://svn.apache.org/viewvc/perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.pm?rev=419300&r1=419299&r2=419300&view=diff
==============================================================================
--- perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.pm (original)
+++ perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.pm Wed Jul  5 11:04:30 2006
@@ -20,65 +20,189 @@
 use strict;
 use vars qw(
     $VERSION
-    $MAX_PROCESS_SIZE
     $REQUEST_COUNT
-    $CHECK_EVERY_N_REQUESTS
-    $MIN_SHARE_SIZE
-    $MAX_UNSHARED_SIZE
     $START_TIME
-    $IS_WIN32
     $USE_SMAPS
 );
 
-$VERSION                = '0.9';
-$CHECK_EVERY_N_REQUESTS = 1;
+$VERSION = '0.9';
+
+__PACKAGE__->set_check_interval(1);
+
 $REQUEST_COUNT          = 1;
-$MAX_PROCESS_SIZE       = 0;
-$MIN_SHARE_SIZE         = 0;
-$MAX_UNSHARED_SIZE      = 0;
-$IS_WIN32               = 0;
 $USE_SMAPS              = 1;
 
-BEGIN {
+use constant IS_WIN32 => $Config{'osname'} eq 'MSWin32' ? 1 : 0;
+
+
+use vars qw( $MAX_PROCESS_SIZE );
+sub set_max_process_size {
+    my $class = shift;
+
+    $MAX_PROCESS_SIZE = shift;
+}
+
+use vars qw( $MAX_UNSHARED_SIZE );
+sub set_max_unshared_size {
+    my $class = shift;
+
+    $MAX_UNSHARED_SIZE = shift;
+}
+
+use vars qw( $MIN_SHARE_SIZE );
+sub set_min_shared_size {
+    my $class = shift;
+
+    $MIN_SHARE_SIZE = shift;
+}
+
+use vars qw( $CHECK_EVERY_N_REQUESTS );
+sub set_check_interval {
+    my $class = shift;
+
+    $CHECK_EVERY_N_REQUESTS = shift;
+}
+
+sub handler ($$) {
+    my $class = shift;
+    my $r = shift || Apache->request;
+
+    return DECLINED unless $r->is_main();
+
+    # we want to operate in a cleanup handler
+    if ( $r->current_callback eq 'PerlCleanupHandler' ) {
+        return $class->_exit_if_too_big($r);
+    }
+    else {
+        $class->add_cleanup_handler($r);
+    }
+
+    return DECLINED;
+}
+
+sub add_cleanup_handler {
+    my $class = shift;
+    my $r = shift || Apache->request;
+
+    return unless $r;
+    return if $r->pnotes('size_limit_cleanup');
+
+    # This used to use $r->post_connection but there's no good way to
+    # test it, since apparently it does not push a handler onto the
+    # PerlCleanupHandler phase. That means that there's no way to use
+    # $r->get_handlers() to check the results of calling this method.
+    $r->push_handlers( 'PerlCleanupHandler',
+                       sub { $class->_exit_if_too_big() } );
+    $r->pnotes( size_limit_cleanup => 1 );
+}
+
+sub _exit_if_too_big {
+    my $class = shift;
+    my $r = shift;
+
+    return DECLINED
+        if ( $CHECK_EVERY_N_REQUESTS
+             && ( $REQUEST_COUNT++ % $CHECK_EVERY_N_REQUESTS ) );
+
+    $START_TIME ||= time;
+
+    if ( $class->_limits_are_exceeded() ) {
+        my ( $size, $share, $unshared ) = $class->_check_size();
+
+        if ( IS_WIN32 || $class->real_getppid() > 1 ) {
+            # this is a child httpd
+            my $e   = time - $START_TIME;
+            my $msg = "httpd process too big, exiting at SIZE=$size KB";
+            $msg .= " SHARE=$share KB UNSHARED=$unshared" if ($share);
+            $msg .= " REQUESTS=$REQUEST_COUNT  LIFETIME=$e seconds";
+            $class->_error_log($msg);
+
+            if (IS_WIN32) {
+                # child_terminate() is disabled in win32 Apache
+                CORE::exit(-2);
+            }
+            else {
+                $r->child_terminate();
+            }
+        }
+        else {
+            # this is the main httpd, whose parent is init?
+            my $msg = "main process too big, SIZE=$size KB ";
+            $msg .= " SHARE=$share KB" if ($share);
+            $class->_error_log($msg);
+        }
+    }
+    return OK;
+}
+
+# REVIEW - Why doesn't this use $r->warn or some other
+# Apache/Apache::Log API?
+sub _error_log {
+    my $class = shift;
+
+    print STDERR "[", scalar( localtime(time) ),
+        "] ($$) Apache::SizeLimit @_\n";
+}
+
+sub _limits_are_exceeded {
+    my $class = shift;
+
+    my ( $size, $share, $unshared ) = $class->_check_size();
+
+    return 1 if $MAX_PROCESS_SIZE  && $size > $MAX_PROCESS_SIZE;
+
+    return 0 unless $share;
+
+    return 1 if $MIN_SHARE_SIZE    && $share < $MIN_SHARE_SIZE;
+
+    return 1 if $MAX_UNSHARED_SIZE && $unshared > $MAX_UNSHARED_SIZE;
 
-    # decide at compile time how to check for a process' memory size.
+    return 0;
+}
+
+sub _check_size {
+    my ( $size, $share ) = _platform_check_size();
+
+    return ( $size, $share, $size - $share );
+}
+
+sub _load {
+    my $mod  = shift;
+
+    eval "require $mod"
+        or die "You must install $mod for Apache::SizeLimit to work on your platform.";
+}
+
+BEGIN {
     if (   $Config{'osname'} eq 'solaris'
         && $Config{'osvers'} >= 2.6 ) {
-        *check_size   = \&_solaris_2_6_size_check;
+        *_platform_check_size   = \&_solaris_2_6_size_check;
         *real_getppid = \&_perl_getppid;
     }
     elsif ( $Config{'osname'} eq 'linux' ) {
-        eval { require Linux::Pid }
-            or die "You must install Linux::Pid for Apache::SizeLimit to work on your platform.";
+        _load('Linux::Pid');
 
         *real_getppid = \&_linux_getppid;
 
         if ( eval { require Linux::Smaps } && Linux::Smaps->new($$) ) {
-            *check_size = \&_linux_smaps_size_check;
+            *_platform_check_size = \&_linux_smaps_size_check;
         }
         else {
             $USE_SMAPS = 0;
-            *check_size = \&_linux_size_check;
+            *_platform_check_size = \&_linux_size_check;
         }
     }
     elsif ( $Config{'osname'} =~ /(?:bsd|aix|darwin)/i ) {
-
         # will getrusage work on all BSDs?  I should hope so.
-        eval "require BSD::Resource;"
-            or die
-            "You must install BSD::Resource for Apache::SizeLimit to work on your platform.";
+        _load('BSD::Resource');
 
-        *check_size   = \&_bsd_size_check;
+        *_platform_check_size   = \&_bsd_size_check;
         *real_getppid = \&_perl_getppid;
     }
-    elsif ( $Config{'osname'} eq 'MSWin32' ) {
-        eval { require Win32::API }
-            or die
-            "You must install Win32::API for Apache::SizeLimit to work on your platform.";
+    elsif (IS_WIN32) {
+        _load('Win32::API');
 
-        $IS_WIN32 = 1;
-
-        *check_size   = \&_win32_size_check;
+        *_platform_check_size   = \&_win32_size_check;
         *real_getppid = \&_perl_getppid;
     }
     else {
@@ -87,13 +211,17 @@
 }
 
 sub _linux_smaps_size_check {
-    return _linux_size_check() unless $USE_SMAPS;
+    my $class = shift;
+
+    return $class->_linux_size_check() unless $USE_SMAPS;
 
     my $s = Linux::Smaps->new($$)->all;
     return ($s->size, $s->shared_clean + $s->shared_dirty);
 }
 
 sub _linux_size_check {
+    my $class = shift;
+
     my ( $size, $resident, $share ) = ( 0, 0, 0 );
 
     if ( open my $fh, '<', '/proc/self/statm' ) {
@@ -101,7 +229,7 @@
         close $fh;
     }
     else {
-        _error_log("Fatal Error: couldn't access /proc/self/status");
+        $class->_error_log("Fatal Error: couldn't access /proc/self/status");
     }
 
     # linux on intel x86 has 4KB page size...
@@ -109,8 +237,10 @@
 }
 
 sub _solaris_2_6_size_check {
+    my $class = shift;
+
     my $size = -s "/proc/self/as"
-        or _error_log("Fatal Error: /proc/self/as doesn't exist or is empty");
+        or $class->_error_log("Fatal Error: /proc/self/as doesn't exist or is empty");
     $size = int( $size / 1024 );
 
     # return 0 for share, to avoid undef warnings
@@ -122,6 +252,8 @@
 }
 
 sub _win32_size_check {
+    my $class = shift;
+
     # get handle on current process
     my $get_current_process = Win32::API->new(
         'kernel32',
@@ -168,98 +300,34 @@
 sub _perl_getppid { return getppid }
 sub _linux_getppid { return Linux::Pid::getppid() }
 
-sub _exit_if_too_big {
-    my $r = shift;
-
-    return DECLINED
-        if ( $CHECK_EVERY_N_REQUESTS
-        && ( $REQUEST_COUNT++ % $CHECK_EVERY_N_REQUESTS ) );
+{
+    # Deprecated APIs
 
-    $START_TIME ||= time;
-
-    my ( $size, $share ) = check_size();
-    my $unshared = $size - $share;
+    sub setmax {
+        my $class = __PACKAGE__;
 
-    if (   ( $MAX_PROCESS_SIZE  && $size > $MAX_PROCESS_SIZE )
-        || ( $MIN_SHARE_SIZE    && $share < $MIN_SHARE_SIZE )
-        || ( $MAX_UNSHARED_SIZE && $unshared > $MAX_UNSHARED_SIZE ) ) {
-        # wake up! time to die.
-        if ( $IS_WIN32 || real_getppid() > 1 ) {
-            # this is a child httpd
-            my $e   = time - $START_TIME;
-            my $msg = "httpd process too big, exiting at SIZE=$size KB";
-            $msg .= " SHARE=$share KB UNSHARED=$unshared" if ($share);
-            $msg .= " REQUESTS=$REQUEST_COUNT  LIFETIME=$e seconds";
-            _error_log($msg);
+        $class->set_max_process_size(shift);
 
-            if ($IS_WIN32) {
-                # child_terminate() is disabled in win32 Apache
-                CORE::exit(-2);
-            }
-            else {
-                $r->child_terminate();
-            }
-        }
-        else {
-            # this is the main httpd, whose parent is init?
-            my $msg = "main process too big, SIZE=$size KB ";
-            $msg .= " SHARE=$share KB" if ($share);
-            _error_log($msg);
-        }
+        $class->add_cleanup_handler();
     }
-    return OK;
-}
-
-# setmax can be called from within a Registry script to tell the server
-# to exit if the script causes the process to grow too big.
-sub setmax {
-    $MAX_PROCESS_SIZE = shift;
-
-    _set_post_conn();
-}
 
-sub setmin {
-    $MIN_SHARE_SIZE = shift;
+    sub setmin {
+        my $class = __PACKAGE__;
 
-    _set_post_conn();
-}
+        $class->set_min_shared_size(shift);
 
-sub setmax_unshared {
-    $MAX_UNSHARED_SIZE = shift;
-
-    _set_post_conn();
-}
-
-sub _set_post_conn {
-    my $r = Apache->request
-        or return;
-
-    return if $r->pnotes('size_limit_cleanup');
+        $class->add_cleanup_handler();
+    }
 
-    $r->post_connection( \&_exit_if_too_big );
-    $r->pnotes( size_limit_cleanup => 1 );
-}
+    sub setmax_unshared {
+        my $class = __PACKAGE__;
 
-sub handler {
-    my $r = shift || Apache->request;
+        $class->set_max_unshared_size(shift);
 
-    return DECLINED unless $r->is_main();
-
-    # we want to operate in a cleanup handler
-    if ( $r->current_callback eq 'PerlCleanupHandler' ) {
-        return _exit_if_too_big($r);
+        $class->add_cleanup_handler();
     }
-    else {
-        $r->post_connection( \&_exit_if_too_big );
-    }
-
-    return DECLINED;
 }
 
-sub _error_log {
-    print STDERR "[", scalar( localtime(time) ),
-        "] ($$) Apache::SizeLimit @_\n";
-}
 
 1;
 
@@ -273,7 +341,9 @@
 =head1 SYNOPSIS
 
     <Perl>
-     $Apache::SizeLimit::MAX_UNSHARED_SIZE = 120 * 1024; # 120MB
+     Apache::SizeLimit->set_max_process_size(150_000);   # Max size in KB
+     Apache::SizeLimit->set_min_shared_size(10_000);     # Min share in KB
+     Apache::SizeLimit->set_max_unshared_size(120_000);  # Max unshared size in KB
     </Perl>
 
     PerlCleanupHandler Apache::SizeLimit
@@ -291,28 +361,49 @@
 You can also limit the frequency that these sizes are checked so that
 this module only checks every N requests.
 
-This module is highly platform dependent, please read the CAVEATS
-section.
+This module is highly platform dependent, please read the
+L<PER-PLATFORM BEHAVIOR> section for details. It is possible that this
+module simply does not support your platform.
 
 =head1 API
 
 You can set set the size limits from a Perl module or script loaded by
-Apache:
+Apache by calling the appropriate class method on C<Apache::SizeLimit>:
+
+=over 4
+
+=item * Apache::SizeLimit->set_max_process_size($size)
+
+This sets the maximum size of the process, including both shared and
+unshared memory.
 
-    use Apache::SizeLimit;
+=item * Apache::SizeLimit->set_max_unshared_size($size)
 
-    Apache::SizeLimit::setmax(150_000);           # Max size in KB
-    Apache::SizeLimit::setmin(10_000);            # Min share in KB
-    Apache::SizeLimit::setmax_unshared(120_000);  # Max unshared size in KB
+This sets the maximum amount of I<unshared> memory the process can
+use.
 
-Then in your Apache configuration, make Apache::SizeLimit a
-C<PerlCleanupHandler>:
+=item * Apache::SizeLimit->set_min_shared_size($size)
+
+This sets the minimum amount of shared memory the process must have.
+
+=back
+
+The two methods related to shared memory size are effectively a no-op
+if the module cannot determine the shared memory size for your
+platform. See L<PER-PLATFORM BEHAVIOR> for more details.
+
+=head2 Running the handler()
+
+There are several ways to make this module actually run the code to
+kill a process.
+
+The simplest is to make C<Apache::SizeLimit> a C<PerlCleanupHandler>
+in your Apache config:
 
     PerlCleanupHandler Apache::SizeLimit
 
-Calling any one of C<setmax()>, C<setmin()>, or C<setmax_unshared()>
-will install C<Apache::SizeLimit> as a cleanup handler for the current
-request, if it's not already installed.
+This will ensure that C<< Apache::SizeLimit->handler() >> is called
+run for all requests.
 
 If you want to combine this module with a cleanup handler of your own,
 make sure that C<Apache::SizeLimit> is the last handler run:
@@ -322,8 +413,8 @@
 Remember, mod_perl will run stacked handlers from right to left, as
 they're defined in your configuration.
 
-You can explicitly call the C<Apache::SizeLimit::handler()> function
-from your own cleanup handler:
+You can also explicitly call the C<< Apache::SizeLimit->handler() >>
+function from your own cleanup handler:
 
     package My::CleanupHandler
 
@@ -334,64 +425,34 @@
         # request
         File::Temp::cleanup();
 
-        return Apache::SizeLimit::handler($r);
+        return Apache::SizeLimit->handler($r);
     }
 
-Since checking the process size can take a few system calls on some
-platforms (e.g. linux), you may want to only check the process size
-every N times. To do so, simple set the
-C<$Apache::SizeLimit::CHECK_EVERY_N_REQUESTS> global.
-
-    $Apache::SizeLimit::CHECK_EVERY_N_REQUESTS = 2;
-
-Now C<Apache::SizeLimit> will only check the process size on every
-other request.
-
-=head2 Deprecated API
-
-Previous versions of this module documented three globals for defining
-memory size limits:
-
 =over 4
 
-=item * $Apache::SizeLimit::MAX_PROCESS_SIZE
-
-=item * $Apache::SizeLimit::MIN_SHARE_SIZE
+=item * Apache::SizeLimit->add_cleanup_handler($r)
 
-=item * $Apache::SizeLimit::MAX_UNSHARED_SIZE
+You can call this method inside a request to run C<Apache::SizeLimit>'s
+C<handler()> method for just that request. If this method is called
+repeatedly, it ensures that it only every adds one cleanup handler.
 
 =back
 
-Direct use of these globals is deprecated, but will continue to work
-for the foreseeable future.
+=head2 Checking Every N Requests
 
-=head1 ABOUT THIS MODULE
+Since checking the process size can take a few system calls on some
+platforms (e.g. linux), you may not want to check the process size for
+every request.
 
-This module was written in response to questions on the mod_perl
-mailing list on how to tell the httpd process to exit if it gets too
-big.
+=over 4
 
-Actually, there are two big reasons your httpd children will grow.
-First, your code could have a bug that causes the process to increase
-in size very quickly. Second, you could just be doing operations that
-require a lot of memory for each request. Since Perl does not give
-memory back to the system after using it, the process size can grow
-quite large.
+=item * Apache::SizeLimit->set_check_interval($interval)
 
-This module will not really help you with the first problem. For that
-you should probably look into C<Apache::Resource> or some other means
-of setting a limit on the data size of your program.  BSD-ish systems
-have C<setrlimit()>, which will kill your memory gobbling processes.
-However, it is a little violent, terminating your process in
-mid-request.
+Calling this causes C<Apache::SizeLimit> to only check the process
+size every C<$interval> requests. If you want this to affect all
+processes, make sure to call this during server startup.
 
-This module attempts to solve the second situation, where your process
-slowly grows over time. It checks memory usage after every request,
-and if it exceeds a threshold, exits gracefully.
-
-By using this module, you should be able to discontinue using the
-Apache configuration directive B<MaxRequestsPerChild>, although for
-some folks, using both in combination does the job.
+=back
 
 =head1 SHARED MEMORY OPTIONS
 
@@ -409,7 +470,7 @@
 physical RAM, allowing most processes to live longer and reducing the
 process churn rate.
 
-=head1 CAVEATS
+=head1 PER-PLATFORM BEHAVIOR
 
 This module is highly platform dependent, since finding the size of a
 process is different for each OS, and some platforms may not be
@@ -423,31 +484,29 @@
 =head2 linux
 
 For linux we read the process size out of F</proc/self/statm>. If you
-are worried about performance, see if the CHECK_EVERY_N_REQUESTS
-option is of benefit.
-
-Since linux 2.6 F</proc/self/statm> does not report the amount of
-memory shared by the copy-on-write mechanism as shared memory. Hence
-decisions made on the basis of C<MAX_UNSHARED_SIZE> or
-C<MIN_SHARE_SIZE> are inherently wrong.
-
-To correct this situation, as of the 2.6.14 release of the kernel,
-there is F</proc/self/smaps> entry for each
-process. F</proc/self/smaps> reports various sizes for each memory
-segment of a process and allows us to count the amount of shared
-memory correctly.
+are worried about performance, you can consider using C<<
+Apache::SizeLimit->set_check_interval() >> to reduce how often this
+read happens.
+
+As of linux 2.6, F</proc/self/statm> does not report the amount of
+memory shared by the copy-on-write mechanism as shared memory. This
+means that decisions made based on shared memory as reported by that
+interface are inherently wrong.
+
+However, as of the 2.6.14 release of the kernel, there is
+F</proc/self/smaps> entry for each process. F</proc/self/smaps>
+reports various sizes for each memory segment of a process and allows
+us to count the amount of shared memory correctly.
 
 If C<Apache::SizeLimit> detects a kernel that supports
-F</proc/self/smaps> and if the C<Linux::Smaps> module is installed it
-will use them instead of F</proc/self/statm>. You can prevent
-C<Apache::SizeLimit> from using F</proc/self/smaps> and turn on the
-old behaviour by setting C<$Apache::SizeLimit::USE_SMAPS> to 0.
+F</proc/self/smaps> and the C<Linux::Smaps> module is installed it
+will use that module instead of F</proc/self/statm>.
 
-NOTE: Reading F</proc/self/smaps> is expensive compared to
+Reading F</proc/self/smaps> is expensive compared to
 F</proc/self/statm>. It must look at each page table entry of a
 process.  Further, on multiprocessor systems the access is
-synchronized with spinlocks. Hence, you may want to set the
-C<CHECK_EVERY_N_REQUESTS> option.
+synchronized with spinlocks. Again, you might consider using C<<
+Apache::SizeLimit->set_check_interval() >>.
 
 =head3 Copy-on-write and Shared Memory
 
@@ -463,9 +522,9 @@
 
     sub handler {
       my $r = shift;
-      my ($size, $shared) = $Apache::SizeLimit::check_size();
+      my ($size, $shared) = $Apache::SizeLimit->_check_size();
       $x =~ tr/a/b/;
-      my ($size2, $shared2) = $Apache::SizeLimit::check_size();
+      my ($size2, $shared2) = $Apache::SizeLimit->_check_size();
       $r->content_type('text/plain');
       $r->print("1: size=$size shared=$shared\n");
       $r->print("2: size=$size2 shared=$shared2\n");
@@ -478,11 +537,11 @@
     PerlResponseHandler X
   </Location>
 
-The parent apache allocates memory for the string in C<$x>. The
-C<tr>-command then overwrites all "a" with "b" if the handler is
-called with an argument. This write is done in place, thus, the
-process size doesn't change. Only C<$x> is not shared anymore by means
-of copy-on-write between the parent and the child.
+The parent Apache process allocates memory for the string in
+C<$x>. The C<tr>-command then overwrites all "a" with "b" if the
+handler is called with an argument. This write is done in place, thus,
+the process size doesn't change. Only C<$x> is not shared anymore by
+means of copy-on-write between the parent and the child.
 
 If F</proc/self/smaps> is available curl shows:
 
@@ -533,6 +592,71 @@
 If your platform is not supported, then please send a patch to check
 the process size. The more portable/efficient/correct the solution the
 better, of course.
+
+=head1 ABOUT THIS MODULE
+
+This module was written in response to questions on the mod_perl
+mailing list on how to tell the httpd process to exit if it gets too
+big.
+
+Actually, there are two big reasons your httpd children will grow.
+First, your code could have a bug that causes the process to increase
+in size very quickly. Second, you could just be doing operations that
+require a lot of memory for each request. Since Perl does not give
+memory back to the system after using it, the process size can grow
+quite large.
+
+This module will not really help you with the first problem. For that
+you should probably look into C<Apache::Resource> or some other means
+of setting a limit on the data size of your program.  BSD-ish systems
+have C<setrlimit()>, which will kill your memory gobbling processes.
+However, it is a little violent, terminating your process in
+mid-request.
+
+This module attempts to solve the second situation, where your process
+slowly grows over time. It checks memory usage after every request,
+and if it exceeds a threshold, exits gracefully.
+
+By using this module, you should be able to discontinue using the
+Apache configuration directive B<MaxRequestsPerChild>, although for
+some folks, using both in combination does the job.
+
+=head1 DEPRECATED APIS
+
+Previous versions of this module documented three globals for defining
+memory size limits:
+
+=over 4
+
+=item * $Apache::SizeLimit::MAX_PROCESS_SIZE
+
+=item * $Apache::SizeLimit::MIN_SHARE_SIZE
+
+=item * $Apache::SizeLimit::MAX_UNSHARED_SIZE
+
+=item * $Apache::SizeLimit::CHECK_EVERY_N_REQUESTS
+
+=item * $Apache::SizeLimit::USE_SMAPS
+
+=back
+
+Direct use of these globals is deprecated, but will continue to work
+for the foreseeable future.
+
+It also documented three functions for use from registry scripts:
+
+=over 4
+
+=item * Apache::SizeLimit::setmax()
+
+=item * Apache::SizeLimit::setmin()
+
+=item * Apache::SizeLimit::setmax_unshared()
+
+=back
+
+Besides setting the appropriate limit, these functions I<also> add a
+cleanup handler to the current request.
 
 =head1 AUTHOR
 

Modified: perl/Apache-SizeLimit/trunk/t/response/TestApache/basic.pm
URL: http://svn.apache.org/viewvc/perl/Apache-SizeLimit/trunk/t/response/TestApache/basic.pm?rev=419300&r1=419299&r2=419300&view=diff
==============================================================================
--- perl/Apache-SizeLimit/trunk/t/response/TestApache/basic.pm (original)
+++ perl/Apache-SizeLimit/trunk/t/response/TestApache/basic.pm Wed Jul  5 11:04:30 2006
@@ -9,22 +9,93 @@
 use Apache::SizeLimit;
 use Config;
 
+use constant ONE_MB => 1024;
+use constant TEN_MB => 1024 * 10;
 
 sub handler {
     my $r = shift;
 
-    plan $r, tests => 2;
+    plan $r, tests => 12;
 
-    my ( $size, $shared ) = Apache::SizeLimit::check_size();
-    cmp_ok( $size, '>', 0, 'proc size is reported > 0' );
+    ok( ! Apache::SizeLimit->_limits_are_exceeded(),
+        'check that _limits_are_exceeded() returns false without any limits set' );
 
- SKIP:
     {
-        skip 'I have no idea what getppid() on Win32 might return', 1
-            if 1 $Config{'osname'} eq 'MSWin32';
+        my ( $size, $shared ) = Apache::SizeLimit->_check_size();
+        cmp_ok( $size, '>', 0, 'proc size is reported > 0' );
 
-        cmp_ok( Apache::SizeLimit::real_getppid(), '>', 1,
-                'real_getppid() > 1' );
+    SKIP:
+        {
+            skip 'I have no idea what getppid() on Win32 might return', 1
+                if $Config{'osname'} eq 'MSWin32';
+
+            cmp_ok( Apache::SizeLimit::real_getppid(), '>', 1,
+                    'real_getppid() > 1' );
+        }
+    }
+
+    {
+        # We can assume this will use _at least_ 10MB of memory, based on
+        # assuming a scalar consumes >= 1K.
+        my @big = ('x') x TEN_MB;
+
+        my ( $size, $shared ) = Apache::SizeLimit->_check_size();
+        cmp_ok( $size, '>', TEN_MB, 'proc size is reported > ' . TEN_MB );
+
+        Apache::SizeLimit->set_max_process_size(ONE_MB);
+
+        ok( Apache::SizeLimit->_limits_are_exceeded(),
+            'check that _limits_are_exceeded() returns true based on max process size' );
+
+    SKIP:
+        {
+            skip 'We cannot get shared memory on this platform.', 3
+                unless $shared > 0;
+
+            cmp_ok( $size, '>', $shared, 'proc size is greater than shared size' );
+
+            Apache::SizeLimit->set_max_process_size(0);
+            Apache::SizeLimit->set_min_shared_size( ONE_MB * 100 );
+
+            ok( Apache::SizeLimit->_limits_are_exceeded(),
+                'check that _limits_are_exceeded() returns true based on min share size' );
+
+            Apache::SizeLimit->set_min_shared_size(0);
+            Apache::SizeLimit->set_max_unshared_size(1);
+
+            ok( Apache::SizeLimit->_limits_are_exceeded(),
+                'check that _limits_are_exceeded() returns true based on max unshared size' );
+        }
+    }
+
+    {
+        # Lame test - A way to check that setting this _does_
+        # something would be welcome ;)
+        Apache::SizeLimit->set_check_interval(10);
+        is( $Apache::SizeLimit::CHECK_EVERY_N_REQUESTS, 10,
+            'set_check_interval set global' );
+    }
+
+    {
+        Apache::SizeLimit->set_max_process_size(0);
+        Apache::SizeLimit->set_min_shared_size(0);
+        Apache::SizeLimit->set_max_unshared_size(0);
+
+        my $handlers = $r->get_handlers('PerlCleanupHandler');
+        is( scalar @$handlers, 0,
+            'there is no PerlCleanupHandler before add_cleanup_handler()' );
+
+        Apache::SizeLimit->add_cleanup_handler($r);
+
+        $handlers = $r->get_handlers('PerlCleanupHandler');
+        is( scalar @$handlers, 1,
+            'there is one PerlCleanupHandler after add_cleanup_handler()' );
+
+        Apache::SizeLimit->add_cleanup_handler($r);
+
+        $handlers = $r->get_handlers('PerlCleanupHandler');
+        is( scalar @$handlers, 1,
+            'there is stil one PerlCleanupHandler after add_cleanup_handler() a second time' );
     }
 
     return OK;

Added: perl/Apache-SizeLimit/trunk/t/response/TestApache/deprecated.pm
URL: http://svn.apache.org/viewvc/perl/Apache-SizeLimit/trunk/t/response/TestApache/deprecated.pm?rev=419300&view=auto
==============================================================================
--- perl/Apache-SizeLimit/trunk/t/response/TestApache/deprecated.pm (added)
+++ perl/Apache-SizeLimit/trunk/t/response/TestApache/deprecated.pm Wed Jul  5 11:04:30 2006
@@ -0,0 +1,42 @@
+package TestApache::deprecated;
+
+use strict;
+use warnings;
+
+use Apache::Test qw(-withtestmore);
+
+use Apache::Constants qw(OK);
+use Apache::SizeLimit;
+
+
+sub handler {
+    my $r = shift;
+
+    plan $r, tests => 5;
+
+    my $handlers = $r->get_handlers('PerlCleanupHandler');
+    is( scalar @$handlers, 0,
+        'there is no PerlCleanupHandler before add_cleanup_handler()' );
+
+    Apache::SizeLimit::setmax( 100_000 );
+    is( $Apache::SizeLimit::MAX_PROCESS_SIZE, 100_000,
+        'setmax changes $MAX_PROCESS_SIZE' );
+
+    Apache::SizeLimit::setmin( 1 );
+    is( $Apache::SizeLimit::MIN_SHARE_SIZE, 1,
+        'setmax changes $MIN_SHARE_SIZE' );
+
+    Apache::SizeLimit::setmax_unshared( 1 );
+    is( $Apache::SizeLimit::MIN_SHARE_SIZE, 1,
+        'setmax_unshared changes $MAX_UNSHARED_SIZE' );
+
+    $handlers = $r->get_handlers('PerlCleanupHandler');
+    is( scalar @$handlers, 1,
+        'there is one PerlCleanupHandler after calling deprecated functions' );
+
+
+    return OK;
+}
+
+
+1;