Mailing List Archive

Best way to debug public modules w/Embperl/mod_perl
Hi,

I have a server using some Embperl apps with several .pm modules preloaded at server startup time.

While working on new apps that may require enhancements to the public modules, I'd like to be able to use private copies of some of the modules during development, without disturbing the "release" versions of these modules being used by other users of the server.

I've been able to get my Embperl app to load private copies of modules under development by manipulating @INC and %INC at the top of my EmbPerl file:

[.-
local @INC = @INC;
(my $LibDir = $0) =~ s|(.*/).*|$1|;
unshift @INC, $LibDir;
local %INC = %INC;
delete @INC{grep {m/MyDir.*MyModuleName/ } keys %INC};
require MyDir::MyModuleName;
import MyDir::MyModuleName;
-]

... and this does indeed load my private local copy of MyDir::ModuleName. This also has the advantage of forcing reloads of MyDir::MyModuleName on every execution of the Embperl app, which I need when I'm working on the module code.

But the problem with this approach is that it seems the child processes in which this code runs are being told to load my private version of MyDir::MyModuleName, obliterating the public version, so the next person that tries to use the same child process to run a public app is going to find that it's trying to work with the compiled code of my private module rather than the public one.

If this is indeed the case, what is the best solution?

Here are some solutions I can think of:

1) For debugging/development, run a separate apache server
on a separate http port

2) Put the modules in a differently-named directory
during testing

3) Force my app to re-load the public version of the
module after processing my request so the public
version's once again available to subsequent users.

4) Somehow force the child process to terminate itself
after my request.

So this whole question really boils down to:

What's the "official" "best practice" for developing and debugging new versions of modules in an Embperl/Modperl environment while other people are using the old versions?

-c

------------------------------------------------------------------------
870 Market Street #1270 (415) 394-9818
San Francisco, CA 94102 (413) 473-0853 fax
------------------------------------------------------------------------
RE: Best way to debug public modules w/Embperl/mod_perl [ In reply to ]
Hi,
>
> I've been able to get my Embperl app to load private copies of
> modules under development by manipulating @INC and %INC at the
> top of my EmbPerl file:
>
>...
> But the problem with this approach is that it seems the child
> processes in which this code runs are being told to load my
> private version of MyDir::MyModuleName, obliterating the public
> version, so the next person that tries to use the same child
> process to run a public app is going to find that it's trying to
> work with the compiled code of my private module rather than the
> public one.
>
> If this is indeed the case, what is the best solution?
>

Yes, this is the case, because the Perl interpreter is global to the child

> Here are some solutions I can think of:
>
> 1) For debugging/development, run a separate apache server
> on a separate http port
>
> 2) Put the modules in a differently-named directory
> during testing
>
> 3) Force my app to re-load the public version of the
> module after processing my request so the public
> version's once again available to subsequent users.
>
> 4) Somehow force the child process to terminate itself
> after my request.
>

I would prefer 1, followed by 2 (you must also rename the package name).
With 3 I am sure you will run in more problems, because Perl is not really
unloading your module/test module only overwriting code with the same name.
4 has the same problems, also I am not aware of a good solution to let the
child terminate.

Gerald




-------------------------------------------------------------
Gerald Richter ecos electronic communication services gmbh
Internetconnect * Webserver/-design/-datenbanken * Consulting

Post: Tulpenstrasse 5 D-55276 Dienheim b. Mainz
E-Mail: richter@ecos.de Voice: +49 6133 925151
WWW: http://www.ecos.de Fax: +49 6133 925152
-------------------------------------------------------------
RE: Best way to debug public modules w/Embperl/mod_perl [ In reply to ]
>> Here are some solutions I can think of:
>>
>> 1) For debugging/development, run a separate apache server
>> on a separate http port
>>
>
>I would prefer 1
>....
>
>Gerald


Gerald,

Thanks for confirming my suspicions. Option #1 is what I have ended up settling on.

For the benefit of sharing my solution with the archives, here is how I am choosing to implement that technique on my Linux Red Hat box:

1) Modify my init.d/httpd file to take an optional "port" argument as arg 2, in which case it starts, stops, or re-starts a private httpd (but using the same config file as apachectl would have done.)

############## /etc/rc.d/init.d/httpd:
#!/bin/sh
#
# Startup script for the Apache Web Server

# Source function library.
. /etc/rc.d/init.d/functions

# See how we were called.
case "$1" in
start)
echo -n "Starting httpd: $2"
if [ ! "x$2" = "x" ]; then
env ALT_PORT=$2 /usr/local/apache/bin/httpd -f \
/etc/httpd.conf/httpd.conf
echo
touch /var/lock/subsys/httpd$2
else
/usr/local/apache/bin/apachectl start
echo
touch /var/lock/subsys/httpd
fi;
;;
stop)
echo -n "Shutting down http: "
if [ ! "x$2" = "x" ]; then
kill `cat /usr/local/apache/logs/httpd.pid.$2`
echo
rm -f /var/lock/subsys/httpd$2
rm -f /usr/local/apache/logs/httpd.pid.$2
else
/usr/local/apache/bin/apachectl stop
echo -n httpd
echo
rm -f /var/lock/subsys/httpd
rm -f /var/run/httpd.pid
fi;
;;
status)
/usr/local/apache/bin/apachectl status
/usr/local/apache/bin/apachectl fullstatus
;;
restart)
if [ ! "x$2" = "x" ]; then
kill -HUP `cat /usr/local/apache/logs/httpd.pid.$2`
else
/usr/local/apache/bin/apachectl restart
fi;
;;
reload)
echo -n "Doing a "graceful" reload of httpd: "
/usr/local/apache/bin/apachectl graceful
echo
;;
*)
echo "Usage: $0 {start|stop|restart|reload|status}"
exit 1
esac

exit 0
##############

2) In httpd.conf, do the old "optional port" trick, but triggered from the environment variable passed by the init.d/httpd script, as follows:

PerlPassEnv ALT_PORT

<Perl>
if ($ENV{ALT_PORT} =~ /^(\d+)$/)
{
print STDERR "Starting on port $1...\n";
$Port = $1;
## PidFile corresponds to the one expected by init.d/httpd:
$PidFile = "/usr/local/apache/logs/httpd.pid.$Port";
}
else
{
$Port = 80;
$PidFile = "/usr/local/apache/logs/httpd.pid";
}
</Perl>


Hope this helps someone,

-chris

------------------------------------------------------------------------
870 Market Street #1270 (415) 394-9818
San Francisco, CA 94102 (413) 473-0853 fax
------------------------------------------------------------------------