perl-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Philippe M. Chiasson" <go...@cpan.org>
Subject Re: [Fwd: Apache::Reload Module]
Date Wed, 18 Jun 2003 05:09:43 GMT
On Fri, 2003-06-13 at 16:02, Steve Hay wrote:
> Hi Stas,
> 
> Stas Bekman wrote:
> 
> > [CC'ing Matt and the dev list] 
> 
> [please be sure to keep me in the loop here -- I'm not subscribed to the 
> dev list]
> 
> > Currently there are two versions of this module. One on CPAN for 
> > mod_perl 1.0, the other inside the mod_perl 2.0 package. The mod_perl 
> > developers collectively maintain the version in 2.0, but not the CPAN 
> > version.  Perhaps what should be done is backport the module in 2.0 to 
> > mod_perl 1.0.
> >
> > Also Philippe may consider to put Apache/Reload.pm into the 1.0 distro 
> > as well. 
> 
> Backporting the version in mp2 to mp1 and including it in mp1 sounds 
> like an excellent idea for the forthcoming 1.28 release.
> 
> Would Matt & Philippe agree to this?
> 
> >
> >
> > Now Steve, to your original question. You want these changes for 
> > mod_perl 1.0, correct? 
> 
> Yes.
> 
> >
> >
> > If you try the version in the 2.0 package it already includes all the 
> > changes that you ask for. However it won't work with 1.0 as is, since 
> > it deploys the 2.0 API. 
> 
> Unless I'm missing something, this doesn't seem to be the case.  I've 
> just downloaded the latest mp2 and checked it out.  It doesn't have a 
> "UndefOnReload" option or any equivalent thereof (and it doesn't 
> automatically do what that option would do all the time either).
> 
> Steve
> 
> >
> >
> >> Could you possibly have a look at it?
> >>
> >> I'm after two things: an "UndefOnReload" option like Apache::StatINC 
> >> has (which I haven't quite got working to my satisfaction yet), and a 
> >> GPL/Artistic license statement (like I recently requested for your 
> >> Apache::Test module, in fact!)
> >>
> >> Many thanks,
> >>
> >> Steve
> >>
> >>
> >> -------- Original Message --------
> >> Subject: Apache::Reload Module
> >> Date: Mon, 19 May 2003 10:12:21 +0100
> >> From: Steve Hay <steve.hay@uk.radan.com>
> >> To: matt@sergeant.org
> >>
> >>
> >>
> >> Hi Matt,
> >>
> >> I'm looking into using your Apache::Reload module as an improvement 
> >> over the Apache::StatINC module, but found that one feature was 
> >> missing from it: the option to have functions undefined on reload to 
> >> avoid all those "Subroutine ... redefined ..." warnings.
> >>
> >> The attached patch provides this option (but not quite to my 
> >> satisfaction).  Specify "PerlSetVar UndefOnReload On" in httpd.conf 
> >> and the handler performs the same undeffing action (using 
> >> Apache::Symbol::undef_functions) as Apache::StatINC does...
> >>
> >> ... well, almost!  Apache::StatINC calls undef_functions(undef, 1) 
> >> which arranges for ONLY functions specified in the EXPORT arrays 
> >> (including a special @EXPORT_EXTRAS array) to be undefined.
> >>
> >> This is not very nice for OO-code which doesn't list its methods in 
> >> the EXPORT arrays, so initially I looked at calling 
> >> undef_functions(undef, 0), which would undefine all functions in the 
> >> class concerned.  However, I found that this includes sub-classes 
> >> too, so, for example, if I have Foo:: functions and Foo::Bar:: 
> >> functions and I edit Foo.pm then all the Foo::Bar:: functions get 
> >> undefined too, but not reloaded since I haven't edited Foo/Bar.pm!
> >>
> >> My latest attempt (in the patch) is 
> >> undef_functions("^${class}::.+::", 0), which will undefine all 
> >> functions in $class, but skips those matching the pattern in the 
> >> first argument.  This avoids the Foo::Bar:: problem described above.
> >>
> >> However, there is still one gremlin left that I don't know how to get 
> >> around.  If Foo use()s the Exporter module then Foo::import is an 
> >> alias for Exporter::import, so when Foo::import is undefined we find 
> >> that Exporter::import is now also undefined (and, of course, doesn't 
> >> get reloaded since Exporter.pm has not been edited)!  This applies to 
> >> any symbols that Foo has imported.
> >>
> >> Can you think of a way around that last problem?  Maybe 
> >> Apache::Symbol needs some work?
> >>
> >> If not, then probably going back to undef_functions(undef, 1) is safer.
> >>
> >> One last point: I want to put this module into a Perl distribution 
> >> that is being shipped with some (commercial, not open source) 
> >> software, and I would need it to have a LICENSE statement somewhere 
> >> in it, which it currently doesn't have.  Preferably the usual blurb 
> >> about "the same terms as Perl itself -- GPL or Artistic" since just 
> >> the GPL (which, sadly, some modules do specify) would not permit 
> >> inclusion in such a commercial distribution.
> >>
> >> A new release with either or both of these things in it would be 
> >> greatly appreciated.

Here is some code I've ripped from an in-house Apache::Reload
equivalent... It's a bit convoluted, but does work quite nicely.

sub _removeModule
{
	my $recursive = shift;
	my $create    = $recursive ? 'rnew' : 'new';

	no strict 'refs';
	my @removed;

	if ($package eq __PACKAGE__ || $package =~ /^(B|Devel)::/ || $package !~ /::/) {#suicide
? I don't think so...

		#we do not attempt to reload either ourselves, B and Devel packages and Top level packages
		return;
	}

	if ($package->can('bootstrap'))    #should be a more safe way to figure it out than this
	{#XS/C code, very bad for now ! BAIL out
		print STDERR "$package contains non-perl code and can't be reloaded for now\n";
		return;
	}

	my $stab = Devel::Symdump->$create($package);

	my @methods = grep {$_ !~ /^(packages|ios|functions)$/} sort keys %{$stab->{'AUTOLOAD'}};

	for my $type ('packages', 'ios', @methods, 'functions')
	{
		(my $dtype = uc $type) =~ s/E?S$//;

		for (sort $stab->_partdump(uc $type))
		{
			s/([\000-\037\177])/ '^' . pack('c',ord($1) ^ 64)/eg;
			next if /::SUPER(::.*)?$/;

			if ($type eq 'scalars')
			{
				next unless defined $$_;
			}
			elsif ($type eq 'packages')
			{
				next unless $recursive;
				push @removed, _removeModule($_, 'recursive');
			}
			elsif ($type eq 'functions')
			{
				my $stash = B::svref_2object(*$_{CODE})->GV->STASH->NAME;
				next if $stash ne $package;
			}
			&{"undef_$dtype"} ($_) if defined &{"undef_$dtype"};
		}
	}

	push @removed, $package;

	(my $filename = $package) =~ s|::|/|g;
	delete $INC{"$filename.pm"};

	print STDERR "UNLOADING OF $package COMPLETE\n";
	return @removed;
}

sub undef_IO
{
	no strict 'refs';
	my $name = shift;

	if (tied(*$name))
	{
		untie(*$name);
	}

	close(*$name);
}

sub undef_FUNCTION
{
	no strict 'refs';
	my $name = shift;
	Apache::Symbol::undef(*{$name}{CODE});
}

sub undef_SCALAR
{
	no strict 'refs';
	my $name = shift;
	undef $$name;
}

sub undef_ARRAY
{
	no strict 'refs';
	my $name = shift;
	undef $$name;
	use strict 'refs';
}

sub undef_HASH
{
	no strict 'refs';
	my $name = shift;
	undef $$name;
	use strict 'refs';
}

The magical bit sovling the problem of imported functions in the current
module is:

my $stash = B::svref_2object(*$_{CODE})->GV->STASH->NAME;
next if $stash ne $package;

Basically, you eliminate methods/functions who's stash isn't the current package's.

It worked fine for quite some time.

Hope this helps.

> >> Best regards,
> >>
> >> Steve
> >>
> >>
> >>
> >> ------------------------------------------------------------------------
> >>
> >> --- Reload.pm.orig    2001-04-22 19:10:00.000000000 +0100
> >> +++ Reload.pm    2003-05-19 09:49:00.000000000 +0100
> >> @@ -100,6 +100,7 @@
> >>          }
> >>      }
> >>      +    my $Undef = ref($r) && (lc($r->dir_config("UndefOnReload")

> >> || '') eq 'on');
> >>           while (my($key, $file) = each %Apache::Reload::INCS) {
> >>          local $^W;
> >> @@ -122,6 +123,13 @@
> >>          }
> >>                   if ($mtime > $Stat{$file}) {
> >> +            if ($Undef) {
> >> +                require Apache::Symbol;
> >> +                my $class = Apache::Symbol::file2class($key);
> >> +                # Skip symbols in subclasses of $class::
> >> +                my $re = "^${class}::.+::";
> >> +                $class->Apache::Symbol::undef_functions($re, 0);
> >> +            }
> >>              delete $INC{$key};
> >>   #           warn "Reloading $key\n";
> >>              if (my $symref = $UndefFields{$key}) {
> >
> >
> >
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
> For additional commands, e-mail: dev-help@perl.apache.org
-- 
--------------------------------------------------------------------------------
Philippe M. Chiasson /gozer\@(cpan|ectoplasm)\.org/ 88C3A5A5 (122FF51B/C634E37B)
http://gozer.ectoplasm.org/    F9BF E0C2 480E 7680 1AE5 3631 CB32 A107 88C3 A5A5
Q: It is impossible to make anything foolproof because fools are so ingenious.
perl -e'$$=\${gozer};{$_=unpack(P7,pack(L,$$));/^JAm_pH\n$/&&print||$$++&&redo}'


Mime
View raw message