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 17:19:00 UTC

svn commit: r419253 - /perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.pm

Author: autarch
Date: Wed Jul  5 08:19:00 2006
New Revision: 419253

URL: http://svn.apache.org/viewvc?rev=419253&view=rev
Log:
All of these changes come from reviewing the code with Perrin at YAPC
...

* Increase the version number to 0.9. This thing has been around
forever, so hopefully we think it works reasonably well ;)

* Change the Win32 code to use the same style as everything else in
the file.

* Remove the "goto" bit in _linux_smaps_size_check() and just use a
normal sub call.

* Lots of doc changes.

Still lots to do to give it a modern API and deprecate the current
one.

Modified:
    perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.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=419253&r1=419252&r2=419253&view=diff
==============================================================================
--- perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.pm (original)
+++ perl/Apache-SizeLimit/trunk/lib/Apache/SizeLimit.pm Wed Jul  5 08:19:00 2006
@@ -30,7 +30,7 @@
     $USE_SMAPS
 );
 
-$VERSION                = '0.06';
+$VERSION                = '0.9';
 $CHECK_EVERY_N_REQUESTS = 1;
 $REQUEST_COUNT          = 1;
 $MAX_PROCESS_SIZE       = 0;
@@ -87,7 +87,7 @@
 }
 
 sub _linux_smaps_size_check {
-    goto &linux_size_check unless $USE_SMAPS;
+    return _linux_size_check() unless $USE_SMAPS;
 
     my $s = Linux::Smaps->new($$)->all;
     return ($s->size, $s->shared_clean + $s->shared_dirty);
@@ -123,13 +123,13 @@
 
 sub _win32_size_check {
     # get handle on current process
-    my $GetCurrentProcess = Win32::API->new(
+    my $get_current_process = Win32::API->new(
         'kernel32',
-        'GetCurrentProcess',
+        'get_current_process',
         [],
         'I'
     );
-    my $hProcess = $GetCurrentProcess->Call();
+    my $proc = $get_current_process->Call();
 
     # memory usage is bundled up in ProcessMemoryCounters structure
     # populated by GetProcessMemoryInfo() win32 call
@@ -138,39 +138,29 @@
 
     # build a buffer structure to populate
     my $pmem_struct = "$DWORD" x 2 . "$SIZE_T" x 8;
-    my $pProcessMemoryCounters
+    my $mem_counters
         = pack( $pmem_struct, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
 
     # GetProcessMemoryInfo is in "psapi.dll"
-    my $GetProcessMemoryInfo = new Win32::API(
+    my $get_process_memory_info = new Win32::API(
         'psapi',
         'GetProcessMemoryInfo',
         [ 'I', 'P', 'I' ],
         'I'
     );
 
-    my $bool = $GetProcessMemoryInfo->Call(
-        $hProcess,
-        $pProcessMemoryCounters,
-        length($pProcessMemoryCounters)
+    my $bool = $get_process_memory_info->Call(
+        $proc,
+        $mem_counters,
+        length $mem_counters,
     );
 
     # unpack ProcessMemoryCounters structure
-    my (
-        $cb,
-        $PageFaultCount,
-        $PeakWorkingSetSize,
-        $WorkingSetSize,
-        $QuotaPeakPagedPoolUsage,
-        $QuotaPagedPoolUsage,
-        $QuotaPeakNonPagedPoolUsage,
-        $QuotaNonPagedPoolUsage,
-        $PagefileUsage,
-        $PeakPagefileUsage
-    ) = unpack( $pmem_struct, $pProcessMemoryCounters );
+    my $peak_working_set_size =
+        ( unpack( $pmem_struct, $mem_counters ) )[2];
 
     # only care about peak working set size
-    my $size = int( $PeakWorkingSetSize / 1024 );
+    my $size = int( $peak_working_set_size / 1024 );
 
     return ( $size, 0 );
 }
@@ -220,8 +210,8 @@
     return OK;
 }
 
-# setmax can be called from within a CGI/Registry script to tell the httpd
-# to exit if the CGI causes the process to grow too big.
+# 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;
 
@@ -244,7 +234,6 @@
     my $r = Apache->request
         or return;
 
-    return if $Apache::Server::Starting || $Apache::Server::ReStarting;
     return if $r->pnotes('size_limit_cleanup');
 
     $r->post_connection( \&_exit_if_too_big );
@@ -284,7 +273,7 @@
 =head1 SYNOPSIS
 
     <Perl>
-     $Apache::SizeLimit::MAX_UNSHARED_SIZE = 120000; # 120MB
+     $Apache::SizeLimit::MAX_UNSHARED_SIZE = 120 * 1024; # 120MB
     </Perl>
 
     PerlCleanupHandler Apache::SizeLimit
@@ -296,8 +285,8 @@
 overall size, by setting a minimum limit on shared memory, or a
 maximum on unshared memory.
 
-You can set limits for each of these sizes, and if any limit is not
-met, the process will be killed.
+You can set limits for each of these sizes, and if any limit is
+exceeded, the process will be killed.
 
 You can also limit the frequency that these sizes are checked so that
 this module only checks every N requests.
@@ -321,22 +310,9 @@
 
     PerlCleanupHandler Apache::SizeLimit
 
-If you want to use C<Apache::SizeLimit> from a registry script, you
-must call one of the above functions for every request:
-
-    use Apache::SizeLimit
-
-    main();
-
-    sub {
-        Apache::SizeLimit::setmax(150_000);
-
-        # handle request
-    };
-
 Calling any one of C<setmax()>, C<setmin()>, or C<setmax_unshared()>
-will install C<Apache::SizeLimit> as a cleanup handler, if it's not
-already installed.
+will install C<Apache::SizeLimit> as a cleanup handler for the current
+request, if it's not already installed.
 
 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:
@@ -347,14 +323,16 @@
 they're defined in your configuration.
 
 You can explicitly call the C<Apache::SizeLimit::handler()> function
-from your own handler:
+from your own cleanup handler:
 
     package My::CleanupHandler
 
     sub handler {
         my $r = shift;
 
-        # do my thing
+        # Causes File::Temp to remove any temp dirs created during the
+        # request
+        File::Temp::cleanup();
 
         return Apache::SizeLimit::handler($r);
     }
@@ -420,8 +398,8 @@
 In addition to simply checking the total size of a process, this
 module can factor in how much of the memory used by the process is
 actually being shared by copy-on-write. If you don't understand how
-memory is shared in this way, take a look at the mod_perl Guide at
-http://perl.apache.org/guide/.
+memory is shared in this way, take a look at the mod_perl docs at
+http://perl.apache.org/docs/.
 
 You can take advantage of the shared memory information by setting a
 minimum shared size and/or a maximum unshared size. Experience on one
@@ -442,14 +420,10 @@
 
 Currently supported OSes:
 
-=over 4
-
-=item linux
+=head2 linux
 
-For linux we read the process size out of F</proc/self/statm>.  This
-is a little slow, but usually not too bad. If you are worried about
-performance, try only setting up the the exit handler inside CGIs
-(with the C<setmax()> function), and see if the CHECK_EVERY_N_REQUESTS
+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
@@ -469,16 +443,13 @@
 C<Apache::SizeLimit> from using F</proc/self/smaps> and turn on the
 old behaviour by setting C<$Apache::SizeLimit::USE_SMAPS> to 0.
 
-C<Apache::SizeLimit> itself will C<$Apache::SizeLimit::USE_SMAPS> to 0
-if it cannot load C<Linux::Smaps> or if your kernel does not support
-F</proc/self/smaps>. Thus, you can check it to determine what is
-actually used.
-
 NOTE: 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 are encouraged to set the C<CHECK_EVERY_N_REQUESTS>
-option.
+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.
+
+=head3 Copy-on-write and Shared Memory
 
 The following example shows the effect of copy-on-write:
 
@@ -488,7 +459,7 @@
     use strict;
     use Apache::Constants qw(OK);
 
-    my $x= "a" x (1024*1024);
+    my $x = "a" x (1024*1024);
 
     sub handler {
       my $r = shift;
@@ -507,11 +478,11 @@
     PerlResponseHandler X
   </Location>
 
-The parent apache allocates a megabyte for the string in C<$x>. The
+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.
+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:
 
@@ -530,7 +501,7 @@
 One can see the kernel lies about the shared memory. It simply doesn't
 count copy-on-write pages as shared.
 
-=item solaris 2.6 and above
+=head2 solaris 2.6 and above
 
 For solaris we simply retrieve the size of F</proc/self/as>, which
 contains the address-space image of the process, and convert to KB.
@@ -540,24 +511,24 @@
 the F</proc> filesystem has changed between 2.5.1 and 2.6. Can anyone
 confirm or deny?
 
-=item *bsd*
+=head2 BSD (and OSX)
 
 Uses C<BSD::Resource::getrusage()> to determine process size.  This is
 pretty efficient (a lot more efficient than reading it from the
 F</proc> fs anyway).
 
-=item AIX?
+=head2 AIX?
 
 Uses C<BSD::Resource::getrusage()> to determine process size.  Not
 sure if the shared memory calculations will work or not.  AIX users?
 
-=item Win32
+=head2 Win32
 
 Uses C<Win32::API> to access process memory information.
 C<Win32::API> can be installed under ActiveState perl using the
 supplied ppm utility.
 
-=back
+=head2 Everything Else
 
 If your platform is not supported, then please send a patch to check
 the process size. The more portable/efficient/correct the solution the
@@ -576,7 +547,17 @@
 <mh...@virage.com>: Win32 support
 
 Dave Rolsky <au...@urth.org>, maintenance and fixes outside of
-mod_perl tree (0.06).
+mod_perl tree (0.04+).
 
 =cut
 
+=head1 TODO
+
+* Create new set/get accessors for all globals, with nice names
+  (set_max_process_size) - keep old names with "push a handler a
+  behavior"
+
+* Add a new "add_cleanup_handler" method to push handler for one
+  request.
+
+=cut