You are viewing a plain text version of this content. The canonical link for it is here.
Posted to docs-cvs@perl.apache.org by st...@apache.org on 2003/08/14 21:11:18 UTC

cvs commit: modperl-docs/src/docs/2.0/api/Apache Reload.pod

stas        2003/08/14 12:11:18

  Modified:    src/docs/2.0/api/Apache Reload.pod
  Log:
  Problems with Scripts Running with Registry Handlers that Cache the
  Code
  
  Revision  Changes    Path
  1.4       +102 -3    modperl-docs/src/docs/2.0/api/Apache/Reload.pod
  
  Index: Reload.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/api/Apache/Reload.pod,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Reload.pod	3 Jun 2003 00:20:44 -0000	1.3
  +++ Reload.pod	14 Aug 2003 19:11:18 -0000	1.4
  @@ -211,16 +211,115 @@
   
   since: mod_perl 1.99_10
   
  -=head1 Problems With Reloading Modules Which Do Not Declare Their Package Name
  +=head1 Caveats
   
  -If you modify modules which don't declare their C<package> and rely on
  -C<Apache::Reload> to reload them you may encounter problems: i.e.,
  +=head2 Problems With Reloading Modules Which Do Not Declare Their Package Name
  +
  +If you modify modules, which don't declare their C<package>, and rely on
  +C<Apache::Reload> to reload them, you may encounter problems: i.e.,
   it'll appear as if the module wasn't reloaded when in fact it
   was. This happens because when C<Apache::Reload> C<require()>s such a
   module all the global symbols end up in the C<Apache::Reload>
   namespace!  So the module does get reloaded and you see the compile
   time errors if there are any, but the symbols don't get imported to
   the right namespace. Therefore the old version of the code is running.
  +
  +=head2 Problems with Scripts Running with Registry Handlers that Cache the Code
  +
  +The following problem is relevant only to registry handlers that cache
  +the compiled script. For example it concerns
  +C<L<ModPerl::Registry|docs::2.0::api::ModPerl::Registry>> but not
  +C<L<ModPerl::PerlRun|docs::2.0::api::ModPerl::PerlRun>>.
  +
  +=head3 The problem
  +
  +Let's say that there is a module C<My::Utils>:
  +
  +  #file:My/Utils.pm
  +  #----------------
  +  package My::Utils;
  +  BEGIN { warn __PACKAGE__ , " was reloaded\n" }
  +  use base qw('Exporter');
  +  @EXPORT = qw(set_colour);
  +  sub colour { "white" }
  +  1;
  +
  +And a registry script F<test.pl>:
  +
  +  #file:test.pl
  +  #------------
  +  use My::Utils;
  +  print "Content-type: text/plain\n\n";
  +  print "the color is " . colour();
  +
  +Assuming that the server is running in a single mode, we request the
  +script for the first time and we get the response:
  +
  +  the color is white
  +
  +Now we change F<My/Utils.pm>:
  +
  +  -  sub colour { "white" }
  +  +  sub colour { "red" }
  +
  +And issue the request again. C<Apache::Reload> does its job and we can
  +see that C<My::Utils> was reloaded (look in the I<error_log>
  +file). However the script still returns:
  +
  +  the color is white
  +
  +=head3 The explanation
  +
  +Even though F<My/Utils.pm> was reloaded, C<ModPerl::Registry>'s cached
  +code won't run 'C<use My::Utils;>' again (since it happens only once,
  +i.e. during the compile time). Therefore the script doesn't know that
  +the subroutine reference has been changed.
  +
  +This is easy to verify. Let's change the script to be:
  +
  +  #file:test.pl
  +  #------------
  +  use My::Utils;
  +  print "Content-type: text/plain\n\n";
  +  my $sub_int = \&colour;
  +  my $sub_ext = \&My::Utils::colour;
  +  print "Content-type: text/plain\n\n";
  +  print "int $sub_int\n";
  +  print "ext $sub_ext\n";
  +
  +Issue a request, you will see something similar to:
  +
  +  int CODE(0x8510af8)
  +  ext CODE(0x8510af8)
  +
  +As you can see both point to the same CODE reference (meaning that
  +it's the same symbol). After modifying F<My/Utils.pm> again:
  +
  +  -  sub colour { "red" }
  +  +  sub colour { "blue" }
  +
  +and calling the script on the secondnd time, we get:
  +
  +  int CODE(0x8510af8)
  +  ext CODE(0x851112c)
  +
  +You can see that the internal CODE reference is not the same as the
  +external one.
  +
  +=head3 The Solution
  +
  +There are two solutions to this problem:
  +
  +Solution 1: replace C<use()> with an explicit C<require()> +
  +C<import()>.
  +
  + - use My::Utils;
  + + require My::Utils; My::Utils->import();
  +
  +now the changed functions will be reimported on every request.
  +
  +Solution 2: remember to touch the script itself every time you change
  +the module that it requires.
   
   =head1 Threaded MPM and Multiple Perl Interpreters
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: docs-cvs-unsubscribe@perl.apache.org
For additional commands, e-mail: docs-cvs-help@perl.apache.org