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 sb...@hyperreal.org on 1999/09/26 01:14:37 UTC
cvs commit: modperl-site/guide CHANGES advocacy.html all.html browserbugs.html config.html control.html databases.html dbm.html debug.html download.html frequent.html guide-src.tar.gz guide.tar.gz hardware.html help.html index.html install.html intro.html mod_perl_guide.ps.gz modules.html multiuser.html obvious.html performance.html perl.html porting.html scenario.html security.html snippets.html start.html status.html strategy.html warnings.html
sbekman 99/09/25 16:14:36
Modified: guide CHANGES advocacy.html all.html browserbugs.html
config.html control.html databases.html dbm.html
debug.html download.html frequent.html
guide-src.tar.gz guide.tar.gz hardware.html
help.html index.html install.html intro.html
mod_perl_guide.ps.gz modules.html multiuser.html
obvious.html performance.html perl.html
porting.html scenario.html security.html
snippets.html start.html status.html strategy.html
warnings.html
Log:
09.26.99 ver 1.16
* Many little things fixed, rewritten - didn't worth listing them all
here.
* index.html: added another search box for only mod_perl FAQs and the
guide provided by perlreference.com
* config: added a note about Apache restarting twice on start
* warnings: added "syntax error at /dev/null" - broken /dev/null
(Doug)
* porting: added "Special Perl Variables" using local()
* multiuser: Added the considerations not to let users to execute their
CGI scripts inside mod_perl server because of file permissions
(non-mod_perl problem) and a possibility to hijack a DBI connection
from Apache::DBI pool of cached connections (Peter Galbavy)
* install: added "Is it possible to tell whether some option was
included" nm() hints (Doug)
* performance: new "PerlSetupEnv Off" (Doug)
* porting: new section "Passing and preserving custom data structures
between handlers" (Ken Williams)
* security: "OK, AUTH_REQUIRED.and FORBIDDEN" in authentication
phase. (Eric Cholet, Jason Bodnar)
* porting: rewrote the "Generating correct HTTP Headers" section, to
talk about HEAD requests, PerlSendHeader, Perl API to handle the
headers generation, Cookie headers, closure methods to send headers
only once.
* Purifications: I'm very grateful to the people who take their time
to help me to improve the guide's readablility. This time Richard
A. Wells and Frank Schoeters submitted a few corrections to the
text. Keep these corrections coming. Thanks!
* porting: extended the "Forking and Starting Sub-processes with
mod_perl" section (Les Mikesell, Randal L. Schwartz )
* porting: Wrote a whole new section "Configuration Files: Writing,
Modifying and Reloading.", which consist of 3 big parts:
Writing Configuration Files
Reloading Configuration Files
Dynamically updating configuration files
* scenario: updated the X-Forwarded-For> section with notes of
non-reliability. (Ask Bjoern Hansen, Vivek Khera)
* porting: started the "Sharing variables between processes" section
(Eric Cholet)
* config: dumping the configuration by <Perl> sections (Eric Cholet)
* performance: prepare_cached() in persistent connections.
* help.pod: updated a link to Jefferey W. Baker's DBI examples
(Jefferey W. Baker)
* a list of mailing list archives was updated (Andreas J. Koenig, Jan
Peter Hecking, Matthew Darwin, Christof Damian, Young, Geoffrey S)
* debug.pod: "Spinning httpds" section from mod_perl.pod
* config.pod: have stolen the sections "PERL METHOD HANDLERS",
"STACKED HANDLERS" and "Perl*Handlers" from mod_perl.pod
* performance.pod: noted the DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl
Options from perl5004delta.pod relevant to mod_perl
* config.pod: wrote sections "PerlModule and PerlRequire directives",
and Perl*Handlers.
* install.pod: "skipping test on this platform" while 'make test'
explained. (Doug)
* warnings.pod: syntax error at /dev/null, explained (Doug)
* started to work on intro.pod to make clear out the differences
between Perl API, Apache::Registry, Apache::PerlRun.
* install.pod: added "mod_auth_dbm nuances" an old notice from
mod_perl_traps page
* porting.pod: Added the explanation of why you cannot use C<__END__>
or C<__DATA__> within C<Apache::Registry> scripts.
* Removed the Cyan background from the postscript version of the
guide. I liked the light grey background when the guide was printed
on the B&W printer, but yes it uses too much toner - so it's gone :)
Revision Changes Path
1.16 +95 -0 modperl-site/guide/CHANGES
Index: CHANGES
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/CHANGES,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- CHANGES 1999/08/17 19:03:28 1.15
+++ CHANGES 1999/09/25 23:13:47 1.16
@@ -1,5 +1,100 @@
This is a CHANGES file for mod_perl guide
+09.20.99 ver 1.16
+
+* Many little things fixed, rewritten - didn't worth listing them all
+ here.
+
+* index.html: added another search box for only mod_perl FAQs and the
+ guide provided by perlreference.com
+
+* config: added a note about Apache restarting twice on start
+
+* warnings: added "syntax error at /dev/null" - broken /dev/null
+ (Doug)
+
+* porting: added "Special Perl Variables" using local()
+
+* multiuser: Added the considerations not to let users to execute their
+ CGI scripts inside mod_perl server because of file permissions
+ (non-mod_perl problem) and a possibility to hijack a DBI connection
+ from Apache::DBI pool of cached connections (Peter Galbavy)
+
+* install: added "Is it possible to tell whether some option was
+ included" nm() hints (Doug)
+
+* performance: new "PerlSetupEnv Off" (Doug)
+
+* porting: new section "Passing and preserving custom data structures
+ between handlers" (Ken Williams)
+
+* security: "OK, AUTH_REQUIRED.and FORBIDDEN" in authentication
+ phase. (Eric Cholet, Jason Bodnar)
+
+* porting: rewrote the "Generating correct HTTP Headers" section, to
+ talk about HEAD requests, PerlSendHeader, Perl API to handle the
+ headers generation, Cookie headers, closure methods to send headers
+ only once.
+
+* Purifications: I'm very grateful to the people who take their time
+ to help me to improve the guide's readablility. This time Richard
+ A. Wells and Frank Schoeters submitted a few corrections to the
+ text. Keep these corrections coming. Thanks!
+
+* porting: extended the "Forking and Starting Sub-processes with
+ mod_perl" section (Les Mikesell, Randal L. Schwartz )
+
+* porting: Wrote a whole new section "Configuration Files: Writing,
+ Modifying and Reloading.", which consist of 3 big parts:
+ Writing Configuration Files
+ Reloading Configuration Files
+ Dynamically updating configuration files
+
+* scenario: updated the X-Forwarded-For> section with notes of
+ non-reliability. (Ask Bjoern Hansen, Vivek Khera)
+
+* porting: started the "Sharing variables between processes" section
+ (Eric Cholet)
+
+* config: dumping the configuration by <Perl> sections (Eric Cholet)
+
+* performance: prepare_cached() in persistent connections.
+
+* help.pod: updated a link to Jefferey W. Baker's DBI examples
+ (Jefferey W. Baker)
+
+* a list of mailing list archives was updated (Andreas J. Koenig, Jan
+ Peter Hecking, Matthew Darwin, Christof Damian, Young, Geoffrey S)
+
+* debug.pod: "Spinning httpds" section from mod_perl.pod
+
+* config.pod: have stolen the sections "PERL METHOD HANDLERS",
+ "STACKED HANDLERS" and "Perl*Handlers" from mod_perl.pod
+
+* performance.pod: noted the DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl
+ Options from perl5004delta.pod relevant to mod_perl
+
+* config.pod: wrote sections "PerlModule and PerlRequire directives",
+ and Perl*Handlers.
+
+* install.pod: "skipping test on this platform" while 'make test'
+ explained. (Doug)
+
+* warnings.pod: syntax error at /dev/null, explained (Doug)
+
+* started to work on intro.pod to make clear out the differences
+ between Perl API, Apache::Registry, Apache::PerlRun.
+
+* install.pod: added "mod_auth_dbm nuances" an old notice from
+ mod_perl_traps page
+
+* porting.pod: Added the explanation of why you cannot use C<__END__>
+ or C<__DATA__> within C<Apache::Registry> scripts.
+
+* Removed the Cyan background from the postscript version of the
+ guide. I liked the light grey background when the guide was printed
+ on the B&W printer, but yes it uses too much toner - so it's gone :)
+
08.17.99 ver 1.15
* Richard A. Wells has kindly reviewed and corrected the following
1.4 +19 -0 modperl-site/guide/advocacy.html
Index: advocacy.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/advocacy.html,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- advocacy.html 1999/08/17 19:03:31 1.3
+++ advocacy.html 1999/09/25 23:13:47 1.4
@@ -43,6 +43,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Thoughts_about_scalability_and_f">Thoughts about scalability and flexibility</A></H1></CENTER>
@@ -119,6 +128,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="hardware.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.17 +3374 -434 modperl-site/guide/all.html
Index: all.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/all.html,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- all.html 1999/08/17 19:03:32 1.16
+++ all.html 1999/09/25 23:13:48 1.17
@@ -30,8 +30,8 @@
<CENTER><P><B>Deploying mod_perl technology to give a rocket speed
to your CGI/perl scripts.</B></P></CENTER>
-<CENTER><P><B>Version 1.15
- Aug, 17 1999</B></P></CENTER>
+<CENTER><P><B>Version 1.16
+ Sep, 26 1999</B></P></CENTER>
<P>
<HR WIDTH="100%"></P>
@@ -49,6 +49,15 @@
<UL>
<LI><A HREF="intro.html#What_is_mod_perl">What is mod_perl</A>
+ <UL>
+
+ <LI><A HREF="intro.html#mod_cgi">mod_cgi</A>
+ <LI><A HREF="intro.html#C_API">C API</A>
+ <LI><A HREF="intro.html#Perl_API">Perl API</A>
+ <LI><A HREF="intro.html#Apache_Registry">Apache::Registry</A>
+ <LI><A HREF="intro.html#Apache_PerlRun">Apache::PerlRun</A>
+ </UL>
+
<LI><A HREF="intro.html#What_will_you_learn">What will you learn</A>
<LI><A HREF="intro.html#References_and_Acknowledgments">References and Acknowledgments</A>
</UL>
@@ -65,48 +74,54 @@
<LI><A HREF="porting.html#Exposing_Apache_Registry_secret">Exposing Apache::Registry secrets</A>
<LI><A HREF="porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it Does Not</A>
<LI><A HREF="porting.html#What_s_different_about_modperl">What's different about modperl</A>
- <UL>
-
- <LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
- <LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
- <LI><A HREF="porting.html#More_package_name_related_issues">More package name related issues</A>
- <LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
- <LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
- <LI><A HREF="porting.html#Using_format_">Using format()</A>
- <LI><A HREF="porting.html#Using_exit_">Using exit()</A>
- <LI><A HREF="porting.html#Running_from_shell">Running from shell</A>
- <LI><A HREF="porting.html#I_O_is_different">I/O is different</A>
- <LI><A HREF="porting.html#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
- <LI><A HREF="porting.html#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
- <LI><A HREF="porting.html#BEGIN_blocks">BEGIN blocks </A>
- <LI><A HREF="porting.html#END_blocks">END blocks</A>
- <LI><A HREF="porting.html#Switches_w_T">Switches -w, -T</A>
- <LI><A HREF="porting.html#strict_pragma">strict pragma</A>
- <LI><A HREF="porting.html#Turning_warnings_ON">Turning warnings ON</A>
- <LI><A HREF="porting.html#diagnostics_pragma">diagnostics pragma</A>
- <LI><A HREF="porting.html#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
- <LI><A HREF="porting.html#Global_Variables">Global Variables</A>
- <LI><A HREF="porting.html#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
- <LI><A HREF="porting.html#Apache_and_syslog">Apache and syslog</A>
- <LI><A HREF="porting.html#Memory_leakage">Memory leakage</A>
- </UL>
-
+ <LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
+ <LI><A HREF="porting.html#Messing_with_INC">Messing with @INC</A>
<LI><A HREF="porting.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
<UL>
<LI><A HREF="porting.html#Restarting_the_server">Restarting the server</A>
- <LI><A HREF="porting.html#Using_Apache_StatINC">Using Apache::StatINC</A>
- <LI><A HREF="porting.html#Reloading_only_specific_files">Reloading only specific files</A>
+ <LI><A HREF="porting.html#Using_Apache_StatINC_for_Develo">Using Apache::StatINC for Development Process</A>
+ <LI><A HREF="porting.html#Configuration_Files_Writing_Mo">Configuration Files: Writing, Modifying and Reloading.</A>
+ <UL>
+
+ <LI><A HREF="porting.html#Writing_Configuration_Files">Writing Configuration Files</A>
+ <LI><A HREF="porting.html#Reloading_Configuration_Files">Reloading Configuration Files</A>
+ <LI><A HREF="porting.html#Dynamically_updating_configurati">Dynamically updating configuration files</A>
+ </UL>
+
<LI><A HREF="porting.html#Reloading_handlers">Reloading handlers</A>
</UL>
+ <LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
+ <LI><A HREF="porting.html#More_package_name_related_issues">More package name related issues</A>
+ <LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
+ <LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
+ <LI><A HREF="porting.html#Using_format_and_write_">Using format() and write()</A>
+ <LI><A HREF="porting.html#Using_exit_">Using exit()</A>
+ <LI><A HREF="porting.html#Running_from_shell">Running from shell</A>
+ <LI><A HREF="porting.html#I_O_is_different">I/O is different</A>
+ <LI><A HREF="porting.html#Special_Perl_Variables">Special Perl Variables</A>
+ <LI><A HREF="porting.html#Generating_correct_HTTP_Headers">Generating correct HTTP Headers</A>
+ <LI><A HREF="porting.html#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
+ <LI><A HREF="porting.html#BEGIN_blocks">BEGIN blocks </A>
+ <LI><A HREF="porting.html#END_blocks">END blocks</A>
+ <LI><A HREF="porting.html#Switches_w_T">Switches -w, -T</A>
+ <LI><A HREF="porting.html#strict_pragma">strict pragma</A>
+ <LI><A HREF="porting.html#Turning_warnings_ON">Turning warnings ON</A>
+ <LI><A HREF="porting.html#diagnostics_pragma">diagnostics pragma</A>
+ <LI><A HREF="porting.html#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
+ <LI><A HREF="porting.html#Global_Variables">Global Variables</A>
+ <LI><A HREF="porting.html#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
+ <LI><A HREF="porting.html#Apache_and_syslog">Apache and syslog</A>
+ <LI><A HREF="porting.html#Memory_leakage">Memory leakage</A>
<LI><A HREF="porting.html#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
<LI><A HREF="porting.html#The_Script_is_too_dirty_but_It_">The Script is too dirty, but It does the job and I can't afford rewriting it.</A>
<LI><A HREF="porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
+ <LI><A HREF="porting.html#Sharing_variables_between_proces">Sharing variables between processes</A>
<LI><A HREF="porting.html#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
<LI><A HREF="porting.html#Finding_the_line_number_the_erro">Finding the line number the error/warning has been triggered at</A>
- <LI><A HREF="porting.html#Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
- <LI><A HREF="porting.html#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A>
+ <LI><A HREF="porting.html#Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A>
+ <LI><A HREF="porting.html#Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A>
</UL>
<P><LI><A HREF="performance.html"><B><FONT SIZE=+1>Performance. Benchmarks.</FONT></B></A></LI><P>
<UL>
@@ -121,6 +136,8 @@
<LI><A HREF="performance.html#Preload_Registry_Scripts">Preload Registry Scripts</A>
<LI><A HREF="performance.html#Avoid_Importing_Functions">Avoid Importing Functions</A>
+ <LI><A HREF="performance.html#PerlSetupEnv_Off">PerlSetupEnv Off</A>
+ <LI><A HREF="performance.html#_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A>
<LI><A HREF="performance.html#Shared_Memory">Shared Memory</A>
<LI><A HREF="performance.html#Checking_script_modification_tim">Checking script modification times</A>
<LI><A HREF="performance.html#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
@@ -224,15 +241,18 @@
</UL>
<LI><A HREF="install.html#Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A>
+ <LI><A HREF="install.html#Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A>
<LI><A HREF="install.html#Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A>
<LI><A HREF="install.html#Server_Installation_problems">Server Installation problems</A>
<UL>
+ <LI><A HREF="install.html#_skipping_test_on_this_plat">......skipping test on this platform</A>
<LI><A HREF="install.html#make_test_fails">make test fails</A>
<LI><A HREF="install.html#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
<LI><A HREF="install.html#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
</UL>
+ <LI><A HREF="install.html#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
<LI><A HREF="install.html#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
</UL>
<P><LI><A HREF="config.html"><B><FONT SIZE=+1>Server Configuration</FONT></B></A></LI><P>
@@ -243,6 +263,14 @@
<LI><A HREF="config.html#Alias_Configurations">Alias Configurations</A>
<LI><A HREF="config.html#Location_Configuration">Location Configuration</A>
+ <LI><A HREF="config.html#PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A>
+ <LI><A HREF="config.html#Perl_Handlers">Perl*Handlers</A>
+ </UL>
+
+ <LI><A HREF="config.html#STACKED_HANDLERS">STACKED HANDLERS</A>
+ <LI><A HREF="config.html#PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A>
+ <UL>
+
<LI><A HREF="config.html#PerlFreshRestart">PerlFreshRestart</A>
<LI><A HREF="config.html#_perl_status_location">/perl-status location</A>
<UL>
@@ -277,12 +305,13 @@
<LI><A HREF="config.html#My_script_works_under_cgi_bin_b">My script works under cgi-bin, but when called via mod_perl I see A 'Save-As' prompt</A>
<LI><A HREF="config.html#Is_there_a_way_to_provide_a_diff">Is there a way to provide a different startup.pl file for each individual virtual host</A>
<LI><A HREF="config.html#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A>
- <LI><A HREF="config.html#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with</A>
+ <LI><A HREF="config.html#A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A>
<LI><A HREF="config.html#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
</UL>
<LI><A HREF="config.html#Configuration_Security_Concerns">Configuration Security Concerns</A>
<LI><A HREF="config.html#Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A>
+ <LI><A HREF="config.html#Apache_restarts_twice_on_start">Apache restarts twice on start</A>
</UL>
<P><LI><A HREF="frequent.html"><B><FONT SIZE=+1>Frequent mod_perl problems</FONT></B></A></LI><P>
<UL>
@@ -348,6 +377,7 @@
<LI><A HREF="warnings.html#RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A>
<LI><A HREF="warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
<LI><A HREF="warnings.html#server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A>
+ <LI><A HREF="warnings.html#syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near "line arguments:"</A>
</UL>
<P><LI><A HREF="security.html"><B><FONT SIZE=+1>Protecting Your Site</FONT></B></A></LI><P>
<UL>
@@ -362,7 +392,8 @@
<LI><A HREF="security.html#Authentication_code_snippets">Authentication code snippets</A>
<UL>
- <LI><A HREF="security.html#Forcing_reauthenticating">Forcing reauthenticating</A>
+ <LI><A HREF="security.html#Forcing_re_authentication">Forcing re-authentication</A>
+ <LI><A HREF="security.html#OK_AUTH_REQUIRED_and_FORBIDDEN_">OK, AUTH_REQUIRED.and FORBIDDEN in Authentication handlers</A>
</UL>
</UL>
@@ -437,6 +468,8 @@
<LI><A HREF="debug.html#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
<LI><A HREF="debug.html#Monitoring_error_log_file">Monitoring error_log file</A>
<LI><A HREF="debug.html#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
+ <LI><A HREF="debug.html#Spinning_httpds">Spinning httpds</A>
+ <LI><A HREF="debug.html#PROFILING">PROFILING</A>
<LI><A HREF="debug.html#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
<LI><A HREF="debug.html#Devel_Peek">Devel::Peek</A>
</UL>
@@ -476,8 +509,6 @@
<P><LI><A HREF="snippets.html"><B><FONT SIZE=+1>Code Snippets</FONT></B></A></LI><P>
<UL>
- <LI><A HREF="snippets.html#Sending_MIME_headers">Sending MIME headers</A>
- <LI><A HREF="snippets.html#How_to_avoid_printing_the_header">How to avoid printing the header more than once</A>
<LI><A HREF="snippets.html#More_on_relative_paths">More on relative paths</A>
<LI><A HREF="snippets.html#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server</A>
<LI><A HREF="snippets.html#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
@@ -585,16 +616,31 @@
<HR>
<P>
-Now you can search the indexed version of the guide at <A
-HREF="http://www.perlreference.com/mod_perl/guide">perlreference.com</A>.
-
<HR>
+
+<A NAME="SEARCH"></A>
+<CENTER>
+<TABLE BORDER=10 CELLSPACING=2 CELLPADDING=8 >
+<TR BGCOLOR="gray" ALIGN=CENTER VALIGN=TOP>
+<TD ALIGN=CENTER VALIGN=TOP>
+<FONT COLOR=WHITE>
+Search mod_perl FAQs along with this guide
+<BR> at www.perlreference.com
+<FORM action="http://perlreference.com/cgi-bin/mod_perl/search.pl" method="GET">
+<INPUT type="text" name="q" value="" SIZE=15>
+<INPUT TYPE="submit" VALUE="Search">
+</FORM>
+</FONT>
+</TD></TR>
+</TABLE>
+</CENTER>
+
<CENTER>
<TABLE BORDER=10 CELLSPACING=2 CELLPADDING=8 >
<TR BGCOLOR="gray" ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=TOP>
<FONT COLOR=WHITE>
-<A NAME="SEARCH">Search perl.apache.org along with this guide.</A>
+Search perl.apache.org along with this guide.
<FORM ACTION="http://search.apache.org/" METHOD="POST">
<INPUT TYPE="text" NAME="keyword" value="" SIZE=15>
<input type="hidden" name="what" value="perl">
@@ -624,7 +670,7 @@
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER><B><FONT SIZE=-1>Written by <A
-HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 08/17/1999
+HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 09/26/1999
</FONT></B></TD>
<TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" BORDER=0 ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></A>
@@ -671,6 +717,15 @@
<UL>
<LI><A HREF="#What_is_mod_perl">What is mod_perl</A>
+ <UL>
+
+ <LI><A HREF="#mod_cgi">mod_cgi</A>
+ <LI><A HREF="#C_API">C API</A>
+ <LI><A HREF="#Perl_API">Perl API</A>
+ <LI><A HREF="#Apache_Registry">Apache::Registry</A>
+ <LI><A HREF="#Apache_PerlRun">Apache::PerlRun</A>
+ </UL>
+
<LI><A HREF="#What_will_you_learn">What will you learn</A>
<LI><A HREF="#References_and_Acknowledgments">References and Acknowledgments</A>
</UL>
@@ -688,6 +743,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="What_is_mod_perl">What is mod_perl</A></H1></CENTER>
@@ -735,6 +799,123 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="mod_cgi">mod_cgi</A></H2></CENTER>
+<P>
+When you run your CGI scripts by using a configuration of:
+
+<P>
+<PRE> ScriptAlias /cgi-bin/ /home/httpd/cgi-bin/
+</PRE>
+<P>
+you run it under a mod_cgi handler, you never define it explicitly. Apache
+does all the configuration work behind the scenes, when you use a
+ScriptAlias.
+
+<P>
+BTW, don't confuse it with a <CODE>ExecCGI</CODE> configuration option, it's being enabled so the script will be executed and
+not returned as a plain file. For example for mod_perl and <CODE>Apache::Registry</CODE> you would use a configuration like:
+
+<P>
+<PRE> <Location /perl>
+ SetHandler perl-script
+ PerlHandler Apache::Registry
+ Options ExecCGI
+ PerlSendHeader On
+ </Location>
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="C_API">C API</A></H2></CENTER>
+<P>
+META: complete
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Perl_API">Perl API</A></H2></CENTER>
+<P>
+META: complete
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Apache_Registry">Apache::Registry</A></H2></CENTER>
+<P>
+From the point of Perl API, <CODE>Apache::Registry</CODE> is just yet another handler that's not conceptually different from any
+other handler. It reads in the file, compiles, executes it and stores into
+the cache. Since the perl interpreter keeps running from child process'
+creation to its death, any code compiled by the interpreter is not removed
+from memory until the child dies.
+
+<P>
+To keep the script names from collisions, it prepends
+<CODE>Apache::ROOT::</CODE> and the mangled path of the URI to the key of the cached script. This key
+is actually a package name, the script resides in. So if you have requested
+a script <CODE>/perl/project/test.pl</CODE>, the scripts would be wrapped in code which starts with package
+declaration of:
+
+<P>
+<PRE> package Apache::ROOT::perl::project::test_e2pl;
+</PRE>
+<P>
+<CODE>Apache::Registry</CODE> also stores the script's last modification time. Everytime the script
+changes, the cached code would be discarded and recompiled using the
+modified source. However, it doesn't check any of the perl libraries the
+script might use.
+
+<P>
+<CODE>Apache::Registry</CODE> overrides the <CODE>CORE::exit()</CODE> with <Apache::exit()>, so the CGI scripts that used the
+<exit()> will run correctly. We will talk about all these details
+indepth later.
+
+<P>
+The last thing <CODE>Apache::Registry</CODE> does, is emulating of the mod_cgi's environment variables. Like <CODE>$ENV{SERVER_NAME}</CODE>, <CODE>$ENV{REMOTE_USER}</CODE>
+and so on. <STRONG>PerlSetupEnv Off</STRONG> disables this feature and saves some memory bits and CPU clocks.
+
+<P>
+From the point of mod_cgi (when you take the script that was running as a
+plain CGI under mod_cgi to run under mod_perl), there is almost no
+difference, but great speed improve, though much heavier memory usage
+(there is no free lunch :).
+
+<P>
+Just rememeber that the code is being cached, so it wouldn't cleanup the
+memory, like you used to with mod_cgi when the script was existing (it
+doesn't exit in mod_perl).
+
+<P>
+Also rememeber that any libraries that your script might
+<CODE>require()</CODE> or <CODE>use()</CODE> wouldn't be recompiled when
+changed.
+
+<P>
+Of course the book will answer all this issues in depth.
+
+<P>
+Just to show you what happens with your script, when it's being executed
+under <CODE>Apache::Registry</CODE>. If we take the simplest code of (URI <CODE>/perl/project/test.pl</CODE>)
+
+<P>
+<PRE> print "Content-type: text/html\n\n";
+ print "It works\n";
+</PRE>
+<P>
+<CODE>Apache::Registry</CODE> will convert it into the following:
+
+<P>
+<PRE> package Apache::ROOT::perl::project::test_e2pl;
+ use Apache qw(exit);
+ sub handler {
+ print "Content-type: text/html\n\n";
+ print "It works\n";
+ }
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Apache_PerlRun">Apache::PerlRun</A></H2></CENTER>
+<P>
+META: Complete
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="What_will_you_learn">What will you learn</A></H1></CENTER>
<P>
This document was written in an effort to help you start using Apache's
@@ -852,8 +1033,8 @@
<P><LI>
<P>
-<STRONG>Eric Cholet</STRONG>, who wrote complete sections for the guide, and pointed out the errors in
-the guide.
+<STRONG>Eric Cholet</STRONG>, who wrote complete sections for the guide, and pointed out the errors the
+guide carried away.
<P><LI>
<P>
@@ -921,6 +1102,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="index.html">Main Page</A> | <A HREF="start.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -934,7 +1125,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/29/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
@@ -1002,18 +1193,26 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="What_s_inside_">What's inside?</A></H1></CENTER>
<P>
-Before you start installing mod_perl, you should have an overall picture of
-this wonderful technology. There is more then one way to use a
+Before you start with mod_perl installation, you should have an overall
+picture of this wonderful technology. There is more then one way to use a
mod_perl-enabled webserver. You have to decide what mod_perl scheme you
-want to use. <A HREF="././strategy.html#">Picking the Right Strategy</A>
-chapter presents various approaches and discusses their pros and cons.
+want to use. <A HREF="././strategy.html#">Picking the Right Strategy</A> chapter presents various approaches and discusses their pros and cons.
<P>
-Once you know what fits your requirements the best, you should proceed to <A HREF="././scenario.html#">Real World Scenarios Implementaion</A>. This chapter provides very detailed scenarios of the schemes discussed in
+Once you know what fits your requirements the best, you should proceed to <A HREF="././scenario.html#">Real World Scenarios Implementation</A>. This chapter provides very detailed scenarios of the schemes discussed in
the
<A HREF="././strategy.html#">Picking the Right Strategy</A> chapter.
@@ -1058,6 +1257,9 @@
the chapter <A HREF="././warnings.html#">Warnings and Errors: Where and Why</A>.
<P>
+<A HREF="././security.html#">Protecting Your Site</A> - Everything regarding security.
+
+<P>
If you are into driving relational databases with your cgi scripts, the <A HREF="././databases.html#">mod_perl and Relational Databases</A> chapter will tell you all about the database-related goodies mod_perl has
prepared for you.
@@ -1070,7 +1272,7 @@
possible? Is it secure? Will it work? What resources does it take? The <A HREF="././multiuser.html#">mod_perl for ISPs. mod_perl and Virtual Hosts</A>
chapter answers all these questions. If you want to run a mod_perl- enabled
server, but do not have root access, read this chapter as well, either to
-learn how do it yourself, or maybe to persuade your ISP to provide this
+learn how to do it yourself, or maybe to persuade your ISP to provide this
service.
<P>
@@ -1115,6 +1317,13 @@
writing the scripts.
<P>
+The <A HREF="././hardware.html#">Choosing an Operating System and Hardware</A> chapter gives you an idea on how to choose the SW and HW for the webserver.
+
+<P>
+The <mod_perl Advocacy|advocacy/> tries to help to make it easier to
+advocate mod_perl around the world.
+
+<P>
The <A HREF="././help.html#">Getting Helped and Further Learning</A> chapter refers you to other related information resources, like learning
Perl programming and SQL, understanding security, building databases, and
more.
@@ -1134,6 +1343,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="intro.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -1147,7 +1366,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/29/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
@@ -1204,48 +1423,54 @@
<LI><A HREF="#Exposing_Apache_Registry_secret">Exposing Apache::Registry secrets</A>
<LI><A HREF="#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it Does Not</A>
<LI><A HREF="#What_s_different_about_modperl">What's different about modperl</A>
- <UL>
-
- <LI><A HREF="#Script_s_name_space">Script's name space</A>
- <LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
- <LI><A HREF="#More_package_name_related_issues">More package name related issues</A>
- <LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
- <LI><A HREF="#Output_from_system_calls">Output from system calls</A>
- <LI><A HREF="#Using_format_">Using format()</A>
- <LI><A HREF="#Using_exit_">Using exit()</A>
- <LI><A HREF="#Running_from_shell">Running from shell</A>
- <LI><A HREF="#I_O_is_different">I/O is different</A>
- <LI><A HREF="#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
- <LI><A HREF="#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
- <LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
- <LI><A HREF="#END_blocks">END blocks</A>
- <LI><A HREF="#Switches_w_T">Switches -w, -T</A>
- <LI><A HREF="#strict_pragma">strict pragma</A>
- <LI><A HREF="#Turning_warnings_ON">Turning warnings ON</A>
- <LI><A HREF="#diagnostics_pragma">diagnostics pragma</A>
- <LI><A HREF="#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
- <LI><A HREF="#Global_Variables">Global Variables</A>
- <LI><A HREF="#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
- <LI><A HREF="#Apache_and_syslog">Apache and syslog</A>
- <LI><A HREF="#Memory_leakage">Memory leakage</A>
- </UL>
-
+ <LI><A HREF="#Script_s_name_space">Script's name space</A>
+ <LI><A HREF="#Messing_with_INC">Messing with @INC</A>
<LI><A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
<UL>
<LI><A HREF="#Restarting_the_server">Restarting the server</A>
- <LI><A HREF="#Using_Apache_StatINC">Using Apache::StatINC</A>
- <LI><A HREF="#Reloading_only_specific_files">Reloading only specific files</A>
+ <LI><A HREF="#Using_Apache_StatINC_for_Develo">Using Apache::StatINC for Development Process</A>
+ <LI><A HREF="#Configuration_Files_Writing_Mo">Configuration Files: Writing, Modifying and Reloading.</A>
+ <UL>
+
+ <LI><A HREF="#Writing_Configuration_Files">Writing Configuration Files</A>
+ <LI><A HREF="#Reloading_Configuration_Files">Reloading Configuration Files</A>
+ <LI><A HREF="#Dynamically_updating_configurati">Dynamically updating configuration files</A>
+ </UL>
+
<LI><A HREF="#Reloading_handlers">Reloading handlers</A>
</UL>
+ <LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
+ <LI><A HREF="#More_package_name_related_issues">More package name related issues</A>
+ <LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
+ <LI><A HREF="#Output_from_system_calls">Output from system calls</A>
+ <LI><A HREF="#Using_format_and_write_">Using format() and write()</A>
+ <LI><A HREF="#Using_exit_">Using exit()</A>
+ <LI><A HREF="#Running_from_shell">Running from shell</A>
+ <LI><A HREF="#I_O_is_different">I/O is different</A>
+ <LI><A HREF="#Special_Perl_Variables">Special Perl Variables</A>
+ <LI><A HREF="#Generating_correct_HTTP_Headers">Generating correct HTTP Headers</A>
+ <LI><A HREF="#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
+ <LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
+ <LI><A HREF="#END_blocks">END blocks</A>
+ <LI><A HREF="#Switches_w_T">Switches -w, -T</A>
+ <LI><A HREF="#strict_pragma">strict pragma</A>
+ <LI><A HREF="#Turning_warnings_ON">Turning warnings ON</A>
+ <LI><A HREF="#diagnostics_pragma">diagnostics pragma</A>
+ <LI><A HREF="#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
+ <LI><A HREF="#Global_Variables">Global Variables</A>
+ <LI><A HREF="#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
+ <LI><A HREF="#Apache_and_syslog">Apache and syslog</A>
+ <LI><A HREF="#Memory_leakage">Memory leakage</A>
<LI><A HREF="#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
<LI><A HREF="#The_Script_is_too_dirty_but_It_">The Script is too dirty, but It does the job and I can't afford rewriting it.</A>
<LI><A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
+ <LI><A HREF="#Sharing_variables_between_proces">Sharing variables between processes</A>
<LI><A HREF="#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
<LI><A HREF="#Finding_the_line_number_the_erro">Finding the line number the error/warning has been triggered at</A>
- <LI><A HREF="#Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
- <LI><A HREF="#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A>
+ <LI><A HREF="#Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A>
+ <LI><A HREF="#Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A>
</UL>
<!-- INDEX END -->
@@ -1261,6 +1486,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Document_Coverage">Document Coverage</A></H1></CENTER>
@@ -1304,9 +1538,15 @@
HREF="http://world.std.com/~swmcd/steven/perl/module_mechanics.html">http://world.std.com/~swmcd/steven/perl/module_mechanics.html</A>
-<P><LI><STRONG><A NAME="item_Mod">Mod Perl Book</A></STRONG>
<P>
-A must have book! See the details at <A
+The information is very relevant to a mod_perl developer.
+
+<P><LI><STRONG><A NAME="item_The">The Eagle Book</A></STRONG>
+<P>
+``Writing Apache Modules with Perl and C'' is a ``must have'' book!
+
+<P>
+See the details at <A
HREF="http://www.modperl.com">http://www.modperl.com</A> .
</UL>
@@ -1482,8 +1722,8 @@
the <CODE>handler</CODE> subroutine.
<P>
-The workaround is to use global declared variables, with <CODE>vars</CODE>
-pragma.
+One of the workarounds is to use global declared variables, with
+<CODE>vars</CODE> pragma.
<P>
<PRE> # !/usr/bin/perl -w
@@ -1528,16 +1768,133 @@
print "Counter is equal to $main::counter !<BR>\n";
}
</PRE>
+<P>
+Another working but not quite good solution, is always to pass the variable
+as an argument. It's not good when the variable can be quite big, so it
+adds an overhead of time and memory.
+
+<P>
+<PRE> #!/usr/bin/perl -w
+ use strict;
+
+ print "Content-type: text/html\r\n\r\n";
+
+ my $counter = 0;
+
+ for (1..5) {
+ increment_counter($counter);
+ }
+
+ sub increment_counter{
+ my $counter = shift || 0 ;
+ $counter++;
+ print "Counter is equal to $counter !<BR>\n";
+ }
+</PRE>
+<P>
+It's important to understand that the closure effect happens only with code
+that <CODE>Apache::Registry</CODE> wraps with a declaration of the
+<CODE>handler</CODE> subroutine. If you put your code into a library or module, which the main
+script <CODE>require()'s</CODE> or <CODE>use()'s,</CODE> there is no such a
+problem. For example if we put the subroutine <CODE>increment_counter()</CODE>
+into a <CODE>mylib.pl</CODE> (e.g. save it in the same directory as the main script) and
+<CODE>require()</CODE> it, there will be no problem at all. (Don't forget
+the <CODE>1;</CODE> at the end of the library or the <CODE>require()</CODE> might fail.)
+
+<P>
+<PRE> mylib.pl:
+ ----------
+ sub increment_counter{
+ $counter++;
+ print "Counter is equal to $counter !<BR>\n";
+ }
+ 1;
+ ----------
+</PRE>
+<P>
+<PRE> counter.pl:
+ ----------
+ #!/usr/bin/perl -w
+ use strict;
+ require "./mylib.pl";
+
+ print "Content-type: text/html\r\n\r\n";
+
+ my $counter = 0;
+
+ for (1..5) {
+ increment_counter();
+ }
+
+ ----------
+</PRE>
+<P>
+Personally, unless the script is too short, I've got used to write all the
+code in the external libraries, and to have only a few lines in the main
+script, generally to call the main function of my library. Usually i call
+it <CODE>init()</CODE>. I don't worry about closure effect anymore (unless I create it myself :).
+
+<P>
+You shouldn't be intimidated by this issue at all, since Perl is your
+friend. Just keep the warnings mode On and whenever you will have this
+effect in place, Perl will gladly tell you that by saying:
+
+<P>
+<PRE> Variable "$counter" will not stay shared at ...[snipped]
+</PRE>
+<P>
+Just don't forget to check your error_log file, before going in production!
+
+<P>
+BTW, the above example was pretty boring. In my first days of using
+mod_perl, I wrote some cool user registration program. I'll show a very
+simple represenataion of this program.
+
+<P>
+<PRE> use CGI;
+ $q = new CGI;
+ my $name = $q->param('name')
+ print_respond();
+
+ sub print_respond{
+ print "Content-type: text/html\n\n";
+ print "Thank you, $name!";
+ }
+</PRE>
<P>
-Now let's proceed to the second mystery. Why did we see inconsistent
-results over numerous reloads. That's very simple. Every time a server gets
-a request to process, it handles it over one of the children, generally in
-a round robin fashion. So if you have 10 httpd children alive, first 10
-reloads might seem to be correct. Since the closure starts to effect from
-the second re-invocation, consequent reloads return unexpected results.
-Moreover children don't serve the same request always consequently, at any
-given moment one of the children could serve more times the same script
-than any other. That's why we saw that strange behavior.
+My boss and I have checked the program at the development server at it
+worked OK. So we decided to put it in production, everything was OK, but my
+boss decided to keep on checking by submitting a variations of his profile.
+Imagine what was the surprise when after submitting his name (let's say
+``Me Boss'' :), he saw a response ``Thank you, Stas Bekman!''. What
+happened is that I tried the production system as well. I was new to
+mod_perl stuff and was so excited with the speed improve, I didn't notice
+the clusure problem and it hit me. At the beginning I thought that may be
+Apache started to confuse connection, by returning responses from other
+people's requests. I was wrong of course. Why didn't we notice this when we
+were trying the system at our development server? Keep reading and you will
+understand what was the problem.
+
+<P>
+Now let's return to our original example and proceed with the second
+mystery we have noticed. Why did we see inconsistent results over numerous
+reloads. That's very simple. Every time a server gets a request to process,
+it handles it over one of the children, generally in a round robin fashion.
+So if you have 10 httpd children alive, first 10 reloads might seem to be
+correct. Since the closure starts to effect from the second re-invocation,
+consequent reloads return unexpected results. Moreover children don't serve
+the same request always consequently, at any given moment one of the
+children could serve more times the same script than any other. That's why
+we saw that strange behavior.
+
+<P>
+And now you understand why we didn't notice the problem with the user
+registration system in the last example I've presented. First we didn't
+look at the error_log files. (As a matter of fact we did, but there were so
+many warnings in there, we couldn't tell what are the important ones and
+what aren't). Then we didn't test the system under
+<CODE>-X</CODE> flag (single mode) and we have had too many server children running to
+notice the problem.
<P>
A workaround is to run the server in a single server mode. You achieve this
@@ -1576,6 +1933,138 @@
sometimes it helps.
<P>
+Sometimes it's very hard to understand what the warning complains about,
+you see the source code, but you cannot understand why some specific
+snippet produces warning. The mystery is in fact that the code can be
+called from different places, e.g when it's a subrotine.
+
+<P>
+I'll show you an example of such code.
+
+<P>
+<PRE> local $^W=1;
+ good();
+ bad();
+
+ sub good{
+ print_value("Perl");
+ }
+
+ sub bad{
+ print_value();
+ }
+
+ sub print_value{
+ my $var = shift;
+ print "My value is $var\n";
+ }
+</PRE>
+<P>
+In the code above, there is a sub that prints the passed value, sub
+<CODE>good</CODE> that passes correctly the value and sub <CODE>bad</CODE> where we forgot to pass it. When we run the script, we get the warning:
+
+<P>
+<PRE> Use of uninitialized value at ./warning.pl line 15.
+</PRE>
+<P>
+We can clearly see that there is an undefined value at the line, that
+attempts to print it:
+
+<P>
+<PRE> print "My value is $var\n";
+</PRE>
+<P>
+But how do we know, why it was undefined? The solution is quite simple.
+What we need is a full stack trace which triggered the warning.
+
+<P>
+The <CODE>Carp</CODE> module comes to help with its <CODE>cluck()</CODE> function. Let's modify the script:
+
+<P>
+<PRE> use Carp ();
+ local $SIG{__WARN__} = \&Carp::cluck;
+
+ local $^W=1;
+ good();
+ bad();
+
+ sub good{
+ print_value("Perl");
+ }
+
+ sub bad{
+ print_value();
+ }
+
+ sub print_value{
+ my $var = shift;
+ print "My value is $var\n";
+ }
+</PRE>
+<P>
+Now when we execute it, we would see:
+
+<P>
+<PRE> Use of uninitialized value at /home/httpd/perl/book/warning.pl line 17.
+ Apache::ROOT::perl::book::warning_2epl::print_value()
+ called at /home/httpd/perl/book/warning.pl line 12
+ Apache::ROOT::perl::book::warning_2epl::bad()
+ called at /home/httpd/perl/book/warning.pl line 5
+ Apache::ROOT::perl::book::warning_2epl::handler('Apache=SCALAR(0x84b1154)')
+ called at /usr/lib/perl5/site_perl/5.005/i386-linux/Apache/Registry.pm line 139
+ eval {...} called at
+ /usr/lib/perl5/site_perl/5.005/i386-linux/Apache/Registry.pm line 139
+ Apache::Registry::handler('Apache=SCALAR(0x84b1154)')
+ called at PerlHandler subroutine `Apache::Registry::handler' line 0
+ eval {...} called at PerlHandler subroutine `Apache::Registry::handler' line 0
+</PRE>
+<P>
+Take a moment to understand the trace, the only part that we are intersted
+in is the one that starts when actuall script is being called, so we can
+skip the <CODE>Apache::Registry</CODE> trace part. So we get:
+
+<P>
+<PRE> Use of uninitialized value at /home/httpd/perl/book/warning.pl line 17.
+ Apache::ROOT::perl::book::warning_2epl::print_value()
+ called at /home/httpd/perl/book/warning.pl line 12
+ Apache::ROOT::perl::book::warning_2epl::bad()
+ called at /home/httpd/perl/book/warning.pl line 5
+</PRE>
+<P>
+which tells us that the code that triggered the warning was:
+
+<P>
+<PRE> Apache::Registry code => bad() => print_value()
+</PRE>
+<P>
+We go into a <CODE>bad()</CODE> and indeed see that we forgot to pass the variable. Of course when you
+write a subroutine like <CODE>print_value</CODE> it could be a good idea to check the passed arguments before starting the
+execution. But it was ``good'' enough to show you how to ease the code
+debugging process.
+
+<P>
+Sure, you would say. I could find the problem by a simple inspectation of
+the code. You are right, but I promise you that your task would be quite
+complicated and time consuming for the code of thousands lines.
+
+<P>
+Notice the <CODE>local()</CODE> keyword, before the settings of the
+<CODE>$SIG{__WARN__}</CODE>. Since it's a global variable, forgetting to use
+<CODE>local()</CODE> will enforce this setting for all the scripts running under the same
+process. And if it's wanted behaviour, for example in the development
+server, you better do it in the startup file, where you can easily switch
+this feature on and off when the server restarts.
+
+<P>
+As you have noticed warnings report the line number the event happened at,
+so it's supposed to help to find the problematic code. The problem is that
+many times the line numbers are incorrect, because certain use of the <EM>eval</EM> operator and ``here'' documents are known to throw off Perl's line
+numbering.
+
+<P>
+META: move here the code that explains the settings of #line
+
+<P>
While having a warning mode turned <STRONG>On</STRONG> is a must in a development server, you better turn it globally <STRONG>Off</STRONG> in a production server, since if every CGI script generates only one
warning per request, and your server serves millions of requests per day -
your log file will eat up all of your disk space and machine will die. My
@@ -1691,7 +2180,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Script_s_name_space">Script's name space</A></H2></CENTER>
+<CENTER><H1><A NAME="Script_s_name_space">Script's name space</A></H1></CENTER>
<P>
Scripts under <CODE>Apache::Registry</CODE> do not run in package <STRONG>main</STRONG>, they run in a unique name space based on the requested URI. For example,
if your URI is <STRONG>/perl/test.pl</STRONG> the package will be called
@@ -1699,18 +2188,1072 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Name_collisions_with_Modules_and">Name collisions with Modules and libs</A></H2></CENTER>
+<CENTER><H1><A NAME="Messing_with_INC">Messing with @INC</A></H1></CENTER>
<P>
-To make things clear before we go into details: each child process has its
-own <CODE>%INC</CODE> hash which is used to store information about its compiled modules. The
-keys of the hash are the names of the modules or parameters passed to <CODE>require()</CODE> (<CODE>use()</CODE>). The values are the full or relative paths to these modules/files. Let's
-say we have
-<CODE>my-lib.pl</CODE> and <CODE>MyModule.pm</CODE> both located at <CODE>/home/httpd/perl/my/</CODE>.
+When you <CODE>use(),</CODE> <CODE>require()</CODE> or <CODE>do()</CODE> a
+file, Perl uses a <CODE>@INC</CODE>
+variable, for a list of directories to search for the file. If the file
+that you want to load is not located in one of the listed directories. You
+have to tell Perl where to find the file.
<P>
-* <CODE>/home/httpd/perl/my/</CODE> is in the <CODE>@INC</CODE> path at the server startup.
+In order to <CODE>require()</CODE> a file located at
+<CODE>/home/httpd/perl/examples/test.pl</CODE> you would:
-<P>
+<UL>
+<P><LI>
+<P>
+Use a relative path to one of the directories in the <CODE>@INC</CODE>. Let's say that one of the directories is <CODE>/home/httpd/perl</CODE>.
+
+<P>
+<PRE> require("examples/test.pl");
+</PRE>
+<P>
+or modify the <CODE>@INC</CODE> on the fly:
+
+<P>
+<PRE> use lib qw("examples");
+ require("test.pl");
+</PRE>
+<P>
+That's when the script might be called from any place. If you always
+execute the script from the directory it resides in (<CODE>examples</CODE>
+here), you can do:
+
+<P>
+<PRE> use lib qw(".");
+ require("test.pl");
+</PRE>
+<P>
+But the latest two snippets would fail the reload by
+<CODE>Apache::StatINC</CODE> module (which helps to automatically reload scripts while developing code)
+since when running under mod_perl, <CODE>@INC</CODE> is being freezed, once the server is up and cannot be updated. The only
+chance to temperarely modify the <CODE>@INC</CODE> is while the script is being loaded and compiled for the first time, and
+when it's done, its value will be reset to the original one. Your only
+chance to change the
+<CODE>@INC</CODE> is to modify it in the startup or Apache configuration files.
+
+<P><LI>
+<P>
+You can write a full path to the script:
+
+<P>
+<PRE> require("/home/httpd/perl/examples/test.pl")
+</PRE>
+<P>
+or
+
+<P>
+<PRE> use lib qw("/home/httpd/perl/examples/");
+ require("test.pl");
+</PRE>
+<P>
+the latter will fail the reload of <CODE>Apache::StatINC</CODE> as above. The former will set a correct entry into a <CODE>%INC</CODE> variable.
+
+<P>
+This approach is quite discouraging, since if you want to move this script
+around -- it's quite difficult since you have to modify the path all the
+time. And it can be pretty painful when you move scripts from development
+to production server.
+
+<P>
+But wait, Graham Barr & Nick Ing-Simmons made a present for you by
+writing the <CODE>FindBin</CODE> module, if you know about this module, you don't need to write a hardcoded
+path. The following snippet does all the work for you:
+
+<P>
+<PRE> use FindBin ();
+ use lib "$FindBin::Bin";
+ use MyModule;
+</PRE>
+<P>
+It works exactly like with hardcoded path, and it sets a correct
+<CODE>%INC</CODE> entry as if you have used the hardcoded path while using
+<CODE>require().</CODE>
+
+</UL>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
+<P>
+When you develop plain CGI scripts, you can just change the code, and rerun
+the CGI from your browser. Since the script isn't cached in memory, the
+next time you call it the server starts up a new perl process, which
+recompiles it from scratch. The effects of any modifications you've applied
+are immediately present.
+
+<P>
+The situation is different with <CODE>Apache::Registry</CODE>, since the whole idea is to get maximum performance from the server. By
+default, the server won't spend the time to check whether any included
+library modules have been changed. It assumes that they weren't, thus
+saving a few milliseconds to <CODE>stat()</CODE> the source file (multiplied by however many modules/libraries you are <CODE>use()</CODE>-ing and/or <CODE>require()</CODE>-ing in your script.) The only check that is being done is whether your
+main script has been changed. So if you have only one script that doesn't
+<CODE>use()</CODE> (or <CODE>require()</CODE>) other perl modules (or packages), there is nothing new about it. If
+however, you are developing a script that includes other modules, the files
+you <CODE>use()</CODE> or <CODE>require()</CODE> aren't being checked whether they have been modified.
+
+<P>
+Acknowledging this, how do we get our modperl-enabled server to recognize
+changes in any library modules? Well, there are a couple of techniques:
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
+<P>
+The simplest approach is to restart the server each time you apply some
+change to your code. See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Using_Apache_StatINC_for_Develo">Using Apache::StatINC for Development Process</A></H2></CENTER>
+<P>
+After restarting the server about 100 times, you will be tired and will
+look for another solutions. Help comes from the
+<CODE>Apache::StatINC</CODE> module.
+
+<P>
+<CODE>Apache::StatINC</CODE> reloads <CODE>%INC</CODE> files when updated on disk. When Perl pulls a file via require, it stores
+the filename in the global hash <CODE>%INC</CODE>. The next time Perl tries to require the same file, it sees the file in <CODE>%INC</CODE> and does not reload from disk. This module's handler iterates over <CODE>%INC</CODE> and reloads the file if it has changed on disk.
+
+<P>
+To enable this module just add two lines to <CODE>httpd.conf</CODE> file.
+
+<P>
+<PRE> PerlModule Apache::StatINC
+ PerlInitHandler Apache::StatINC
+</PRE>
+<P>
+To be sure it really works, turn on the debug mode on your development box
+with <CODE>PerlSetVar StatINCDebug On</CODE>. You end up with something like:
+
+<P>
+<PRE> PerlModule Apache::StatINC
+ <Location /perl>
+ SetHandler perl-script
+ PerlHandler Apache::Registry::handler
+ Options ExecCGI
+ PerlSendHeader On
+ PerlInitHandler Apache::StatINC
+ PerlSetVar StatINCDebug On
+ </Location>
+</PRE>
+<P>
+Beware that only the modules located in <CODE>@INC</CODE> are being reloaded on change, and you can change the <CODE>@INC</CODE> only before the server has been started (in startup file).
+
+<P>
+Whatever you do in your scripts and modules which are being <CODE>required()</CODE> after the server startup will not have any effect on <CODE>@INC</CODE>. When you do:
+
+<P>
+<PRE> use lib qw(foo/bar);
+</PRE>
+<P>
+the <CODE>@INC</CODE> is being changed only for the time the code is being parsed and compiled.
+When it's over the <CODE>@INC</CODE> is being reset to its original value. To make sure that you have set a
+correct <CODE>@INC</CODE> fetch <A
+HREF="http://www.nowhere.com/perl-status?inc">http://www.nowhere.com/perl-status?inc</A>
+and look at the bottom of the page. (I assume you have configured the <A HREF="././config.html#_perl_status_location">/perl-status location</A>.)
+
+<P>
+Also, notice the following caveat: While ``<CODE>.</CODE>'' is in the <CODE>@INC</CODE> -- perl knows to <CODE>require()</CODE> files relative to the script directory. Once the script was parsed - the
+server doesn't remember the path any more! So you end up with broken entry
+in <CODE>%INC</CODE> like:
+
+<P>
+<PRE> $INC{bar.pl} eq "bar.pl"
+</PRE>
+<P>
+If you want Apache::StatINC to reload your script - modify the <CODE>@INC</CODE>
+at the server startup file! or use a full path in <CODE>require()</CODE> call.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Configuration_Files_Writing_Mo">Configuration Files: Writing, Modifying and Reloading.</A></H2></CENTER>
+<P>
+Checking all the modules in <STRONG>%INC</STRONG> every time can add a large overhead to server response times, and you
+certainly would not want
+<CODE>Apache::StatINC</CODE> module to be enabled in your production site's configuration. But sometimes
+you want to have a configuration file to be reloaded when this updated,
+without restarting the server.
+
+<P>
+This is especially important feature if you have a person that is allowed
+to modify some of the tool configuration, but it's very undesirable for
+this person to telnet to the server to restart it, for either this admin
+person's lack of profeccional skills or because of security reasons -- you
+don't want to give a root password, unless you have to.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H3><A NAME="Writing_Configuration_Files">Writing Configuration Files</A></H3></CENTER>
+<P>
+Since we are talking about configuration files, I would like to jump on
+this and show you some good and bad approaches of configuration file
+writing.
+
+<P>
+If you have a configuration file of just a few variables, it doesn't really
+matter how you do it. But generally this is not a case. Configuration files
+tend to grow as a project grows. It's very relevant to the projects that
+generate HTML files, since the they tend to demand many easily configurable
+parameters, like headers, tails, colors and so on.
+
+<P>
+So let's start from the basic approach that is being mostly deployed by
+many CGI scripts writers. This approach is based on having many variables
+defined in a separate configuration file. For example:
+
+<P>
+<PRE> $cgi_dir = "/home/httpd/perl";
+ $cgi_url = "/perl";
+ $docs_dir = "/home/httpd/docs";
+ $docs_url = "/";
+ $img_dir = "/home/httpd/docs/images";
+ $img_url = "/images";
+ ... many more config params here ...
+ $color_hint = "#777777";
+ $color_warn = "#990066";
+ $color_normal = "#000000";
+</PRE>
+<P>
+Now when we want to use these variables in the mod_perl script we must
+declare them all with help of <CODE>use vars</CODE> in the script, because of the <CODE>use strict;</CODE> pragma, which demands all the variables to be declared if used in the
+script.
+
+<P>
+So we start the script with:
+
+<P>
+<PRE> use strict;
+ use vars qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal
+ );
+</PRE>
+<P>
+This is a nightmare to maintain such a script, especially if not all the
+features were written yet, so you keep adding and reming the names to the
+list. But that's not a big deal.
+
+<P>
+Since we want our code clean, we start the configuration file with
+<CODE>use strict;</CODE> as well, so we have to list the variables here as well. Second list to
+maintain.
+
+<P>
+The moment you will have many scripts, you will get into a problem of
+collisions between configuration files, where one of the best solutions is
+a package declaration, which makes the scripts unique (if you declare
+unique package names of course).
+
+<P>
+The moment you add a package declaration and think that you are done, you
+just realize that the nightmare has just begun. The moment you have
+declared the package, you cannot just <CODE>require()</CODE> the file and
+use the variables, since they now belong to a different package. So you
+have ether to modify all you script to use a fully qualified notation like <CODE>$My::Config::cgi_url</CODE> instead of just <CODE>$cgi_url</CODE> or to import the need variables into a script that is going to use them.
+
+<P>
+Since you don't want extra typing to make the variables fully qualified,
+you would go for importing approach. But your configuration package has to
+export them first. It means that you have to list all the variables again
+and now to keep at least three variable lists updated, when you do some
+changes in the naming of the configuration variables. And that's when you
+have only one script that uses the configuration file, in a general case
+you have many of them. So now our example of config file looks like that.
+
+<P>
+<PRE> package My::Config;
+ use strict;
+
+ BEGIN {
+ use Exporter ();
+
+ @My::HTML::ISA = qw(Exporter);
+ @My::HTML::EXPORT = qw();
+ @My::HTML::EXPORT_OK = qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal);
+ }
+
+ use vars qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal
+ );
+
+ $cgi_dir = "/home/httpd/perl";
+ $cgi_url = "/perl";
+ $docs_dir = "/home/httpd/docs";
+ $docs_url = "/";
+ $img_dir = "/home/httpd/docs/images";
+ $img_url = "/images";
+ ... many more config params here ...
+ $color_hint = "#777777";
+ $color_warn = "#990066";
+ $color_normal = "#000000";
+</PRE>
+<P>
+And in the code:
+
+<P>
+<PRE> use strict;
+ use My::Config qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal
+ );
+ use vars qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal
+ );
+</PRE>
+<P>
+But as we know this approach is especially bad in a context of mod_perl
+usage, since exported variables add a memory overhead. The more variables
+are being exported the more memory you use. Now as usual we rememeber to
+multiply this overhead by number of the servers we are going to run and we
+receive a pretty big number, which could be used to run a few more servers
+instead.
+
+<P>
+As a matter of fact things aren't so horrible, since you can group your
+variables, and call the groups by special names called tags, which can
+later be used as arguments to the <CODE>import()</CODE> or
+<CODE>use().</CODE> You probably familiar with:
+
+<P>
+<PRE> use CGI qw(:standard :html);
+</PRE>
+<P>
+We can implement it quite easily, with help of <CODE>exporter_tags()</CODE>
+and <CODE>export_ok_tags()</CODE> from <CODE>Exporter</CODE>. For example:
+
+<P>
+<PRE> BEGIN {
+ use Exporter ();
+ use vars qw( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw();
+ @EXPORT_OK = qw();
+
+ %EXPORT_TAGS = (
+ vars => [qw($fname $lname)],
+ subs => [qw(reread_conf untaint_path)],
+ );
+ Exporter::export_ok_tags('vars');
+ Exporter::export_ok_tags('subs');
+ }
+</PRE>
+<P>
+Yes, you export subroutines exactly like variables, since what's actually
+being exported is a symbol. The definition of these subroutines is not
+shown here.
+
+<P>
+In your code now you can write:
+
+<P>
+<PRE> use My::Config qw(:subs :vars);
+</PRE>
+<P>
+Regarding groups of groups. Like the <CODE>:all</CODE> tag from <CODE>CGI.pm</CODE>, which is a group tag of all other groups. It will require a little more
+magic from your side, but you can always save your time and look up the
+solution inside the code of <CODE>CGI.pm</CODE>. It's just a matter of a little code to expand all the groups recursively.
+
+<P>
+After going through a pain of maintaining a list of variables in a big
+project with a huge configuration file (more than 100 variables) and many
+files actually using them, I have come up with a much simpler solution,
+using a single hash, and having all the variables kept inside. Now my
+configuration file looks like:
+
+<P>
+<PRE> package My::Config;
+ use strict;
+
+ BEGIN {
+ use Exporter ();
+
+ @My::Config::ISA = qw(Exporter);
+ @My::Config::EXPORT = qw();
+ @My::Config::EXPORT_OK = qw(%c);
+ }
+
+ use vars qw(%c);
+
+ %c =
+ (
+ dir => {
+ cgi => "/home/httpd/perl",
+ docs => "/home/httpd/docs",
+ img => "/home/httpd/docs/images",
+ },
+ url => {
+ cgi => "/perl",
+ docs => "/",
+ img => "/images",
+ },
+ color => {
+ hint => "#777777",
+ warn => "#990066",
+ normal => "#000000",
+ },
+ );
+</PRE>
+<P>
+A good perl style suggests keeping a comma at the end of lists. That's
+because additional items are tend to be added to the end of the list, and
+when you keep a last comma in place, you never have to remember to add one
+when you add a new item.
+
+<P>
+So now the script looks like:
+
+<P>
+<PRE> use strict;
+ use My::Config qw(%c);
+ use vars qw(%c)
+ print "Content-type: text/plain\n\n";
+ print "My url docs root: $c{url}{docs}\n";
+</PRE>
+<P>
+Do you see the difference? The whole mess has gone, there is only one
+variable to worry about.
+
+<P>
+So far so good, but let's make it even better. I would like to get rid of <CODE>Exporter</CODE> stuff at all. I remove all the exporting code so my config file now looks
+like:
+
+<P>
+<PRE> package My::Config;
+ use strict;
+ use vars qw(%c);
+
+ %c =
+ (
+ dir => {
+ cgi => "/home/httpd/perl",
+ docs => "/home/httpd/docs",
+ img => "/home/httpd/docs/images",
+ },
+ url => {
+ cgi => "/perl",
+ docs => "/",
+ img => "/images",
+ },
+ color => {
+ hint => "#777777",
+ warn => "#990066",
+ normal => "#000000",
+ },
+ );
+</PRE>
+<P>
+And the code
+
+<P>
+<PRE> use strict;
+ use My::Config ();
+ print "Content-type: text/plain\n\n";
+ print "My url docs root: $My::Config::c{url}{docs}\n";
+</PRE>
+<P>
+Since we still want to save us lots of typing, since now we need to use a
+fully qualified notation like in <CODE>$My::Config::c{url}{docs}</CODE>, let's use a magical perl's aliasing feature. I'll modify the code to be:
+
+<P>
+<PRE> use strict;
+ use My::Config ();
+ use vars qw(%c);
+ *c = \%My::Config::c;
+ print "Content-type: text/plain\n\n";
+ print "My url docs root: $c{url}{docs}\n";
+</PRE>
+<P>
+I have alised <CODE>*c</CODE> glob with <CODE>\%My::Config::c</CODE> hash reference. From now on <CODE>%My::Config::c</CODE> and <CODE>%c</CODE> are the same hash. You can read from or modify any of them, both variables
+are the same one.
+
+<P>
+Just one last little notice. Sometimes you see a lot of redundance in the
+configuration variables, like:
+
+<P>
+<PRE> $cgi_dir = "/home/httpd/perl";
+ $docs_dir = "/home/httpd/docs";
+ $img_dir = "/home/httpd/docs/images";
+</PRE>
+<P>
+Now if you want to move the base path <CODE>"/home/httpd"</CODE> into a new place, it demands lots of typing. Of course the solution is:
+
+<P>
+<PRE> $base = "/home/httpd";
+ $cgi_dir = "$base/perl";
+ $docs_dir = "$base/docs";
+ $img_dir = "$base/docs/images";
+</PRE>
+<P>
+But you cannot do the same trick with hash. This wouldn't work:
+
+<P>
+<PRE> %c =
+ (
+ base => "/home/httpd",
+ dir => {
+ cgi => "$base/perl",
+ docs => "$base/docs",
+ img => "$base/docs/images",
+ },
+ );
+</PRE>
+<P>
+But nothing stops us from adding additional variables, which are lexically
+scoped with <CODE>my().</CODE> The following code is correct.
+
+<P>
+<PRE> my $base = "/home/httpd";
+ %c =
+ (
+ dir => {
+ cgi => "$base/perl",
+ docs => "$base/docs",
+ img => "$base/docs/images",
+ },
+ );
+</PRE>
+<P>
+We have just learned how to make configuration files easily maintainable,
+and how to save memory by avoiding variables exporting into a script's
+namespace.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H3><A NAME="Reloading_Configuration_Files">Reloading Configuration Files</A></H3></CENTER>
+<P>
+Now back to the task of dynamically reloading of configuration files.
+
+<P>
+First, lets see a simple case, when we just have to watch after a simple
+configuration file, like this one. Imagine a script that tells who is patch
+pumkin of the current perl release.
+
+<P>
+Sidenote: <jargon> A humourous term for the token - the object
+(notional or real) that gives its possessor (the ``pumpking'' or the
+``pumpkineer'') exclusive access to something, e.g. applying patches to a
+master copy of source (for which the pumpkin is called a ``patch
+pumpkin'').
+
+<P>
+<PRE> use CGI ();
+ use strict;
+
+ my $fname = "Larry";
+ my $lname = "Wall";
+ my $q = new CGI;
+
+ print $q->header(-type=>'text/html');
+ print $q->p("$fname $lname holds the patch pumpkin
+ for this perl release.");
+</PRE>
+<P>
+The script has a hardcoded value for the name. It's very simple: initialize
+the CGI object, print the proper HTTP header and tell the world who is the
+current patch pumpkin.
+
+<P>
+When the patch pumkin changes we don't want to modify the script.
+Therefore, we put the <CODE>$fname</CODE> and <CODE>lname</CODE> variables into a configuration file.
+
+<P>
+<PRE> $fname = "Gurusamy";
+ $lname = "Sarathy";
+ 1;
+</PRE>
+<P>
+Please notice that there is no package declaration in the above file, so
+the code will be evaluated in the caller's package or in the
+<CODE>main::</CODE> package if none was declared. It means that variables
+<CODE>$fname</CODE> and <CODE>$lname</CODE> will override (or initialize if they weren't yet) the variables with the
+same names in the caller's namespace. This works for global variables only
+-- you cannot update lexically defined (with <CODE>my())</CODE> variables
+by this technique.
+
+<P>
+You have started the server and everything is working properly. After a
+while you decide to modify the configuration. How do you let your running
+know, that the configuration was modified, without restarting the server,
+remember we are in production and server restarting can be quite expensive
+for us. ? One of the simplest solutions is to poll the file's modification
+time by calling <CODE>stat()</CODE> before the script starts to do a real
+work, and if we see that the file was updated, we force a reconfiguration
+of the variables located in this file. We will call the function that
+reloads the configuration <CODE>reread_conf()</CODE> and it accepts a
+single argument, which is a relative path to the configuration file.
+
+<P>
+If your CGI script is being invoked under <CODE>Apache::Registry</CODE> handler, you can put the configuration file in the same directory as a
+script or below it and path a relative path to the file, since
+<CODE>Apache::Registry</CODE> calls a <CODE>chdir()</CODE> to the script's directory before it starts the
+script's execution. Otherwise you would have to make sure that the file
+will be found. <CODE>do()</CODE> does search the <CODE>@INC</CODE>
+libraries.
+
+<P>
+<PRE> use vars qw(%MODIFIED);
+ sub reread_conf{
+ my $file = shift;
+ return unless $file;
+ return unless -e $file and -r _;
+ unless ($MODIFIED{$file} and $MODIFIED{$file} == -M _){
+ my $return;
+ unless ($return = do $file) {
+ warn "couldn't parse $file: $@" if $@;
+ warn "couldn't do $file: $!" unless defined $return;
+ warn "couldn't run $file" unless $return;
+ }
+ $MODIFIED{$file} = -M _; # Update the MODIFICATION times
+ }
+ } # end of reread_conf
+</PRE>
+<P>
+We use <CODE>do()</CODE> to reload the code in this file and not
+<CODE>require()</CODE> because, <CODE>do()</CODE> reloads the file
+unconditionally, while <CODE>require()</CODE> will not load the file if it
+was already loaded in one of the previous requests, since there will be an
+entry in the <CODE>%INC</CODE> where the key is the name of the file and the value the path to it. That's
+how Perl keeps track of loaded files and saves overhead of reloading when
+it has to load the same file again. You generally doesn't notice that with
+plain perl scripts, but in mod_perl it's being used all the time (since the
+same script is being reloaded all the time, and all the
+<CODE>require()'s</CODE> files are already loaded after a first request for
+each process.
+
+<P>
+Nevertheless, <CODE>do()</CODE> keeps track of the current filename for
+error messages, searches the <CODE>@INC</CODE> libraries, updates the <CODE>%INC</CODE> if the file is found.
+
+<P>
+To explain all the possible warnings the script emits if something went
+wrong with operation, it's just for a matter of completeness. Generally you
+would do all these checks. If <CODE>do()</CODE> cannot read the file, it returns <CODE>undef</CODE> and sets <CODE>$!</CODE> to the error. If <CODE>do()</CODE> can read the file but cannot compile it, it returns <CODE>undef</CODE> and sets an error message in <CODE>$@</CODE>. If the file is successfully compiled, <CODE>do()</CODE>
+returns the value of the last expression evaluated.
+
+<P>
+Also the configuration file can be broken if someone has incorrectly
+modified it. We don't want the service to go broken, because of that. We
+just trap the possible failure to <CODE>do()</CODE> the file and ignore the
+changes, by the resetting the modification time. It might be a good idea to
+send an email to system administrator about the problem.
+
+<P>
+Notice however, that since <CODE>do()</CODE> updates the <CODE>%INC</CODE> like <CODE>require()</CODE> does, if you are using <CODE>Apache::StatINC</CODE>, it will attempt to reload this file before the <CODE>reread_conf()</CODE>
+call, so if it the file wouldn't compile the request would be aborted. This
+shouldn't be a problem since <CODE>Apache::StatINC</CODE> shouldn't be used in production (because it slows things down by
+<CODE>stat()'ing</CODE> all the files listed in <CODE>%INC</CODE>).
+
+<P>
+Note that we assume that the entire purpose of this function is to reload
+the configuration if that was changed, that's why there is no possible
+failure for this function. If something goes wrong we just return. This
+approach would be incorrect if you are going to initialize the variables
+thru this method on the first invocation of the script. If you do, you will
+want to replace each occurence of <CODE>return()</CODE> and
+<CODE>warn()</CODE> with <CODE>die().</CODE>
+
+<P>
+I used the above approach when I've had a huge configuration file that was
+loaded only once at the server startup, and another little configuration
+file that included only a few variables that could be updated by hand or
+through the web interface, and those variables were duplicates in the main
+config file.
+
+<P>
+So if webmaster breaks the syntax in this dynamic file while updating it by
+hand, it wouldn't affect the main configuration file (which was
+write-protected) and so the proper executing of the programs. Soon we will
+see a simple web interface which allows to modify the configuration file
+without actually breaking it.
+
+<P>
+A sample script using the presented subroutine would be:
+
+<P>
+<PRE> use vars qw(%MODIFIED $fname $lname);
+ use CGI ();
+ use strict;
+
+ my $q = new CGI;
+ print $q->header(-type=>'text/plain');
+ my $config_file = "./config.pl";
+ reread_conf($config_file);
+ print $q->p("$fname $lname holds the patch pumpkin
+ for this perl release.");
+
+ sub reread_conf{
+ my $file = shift;
+ return unless $file;
+ return unless -e $file and -r _;
+ unless ($MODIFIED{$file} and $MODIFIED{$file} == -M _){
+ my $return;
+ unless ($return = do $file) {
+ warn "couldn't parse $file: $@" if $@;
+ warn "couldn't do $file: $!" unless defined $return;
+ warn "couldn't run $file" unless $return;
+ }
+ $MODIFIED{$file} = -M _; # Update the MODIFICATION times
+ }
+ } # end of reread_conf
+</PRE>
+<P>
+Remember that you should be using <CODE>(stat $file)[9]</CODE> instead of <CODE>-M
+$file</CODE> if you are modifying the <CODE>$^M</CODE> variable. In some of my scripts, I reset <CODE>$^M</CODE> to the time of the script invocation with
+<CODE>"$^M = time()"</CODE>, so I can perform <CODE>-M</CODE> and alike (<CODE>-A</CODE>, <CODE>-C</CODE>) file status testings relative to the script invocation time and not the
+time the process was started.
+
+<P>
+If your configuration file is more sophisticated and it declares a package
+and exports variables, the above code will work just as well. Even if you
+think that you will have to re-import() variables, they are just there and
+when do recompiles the code, the originally imported variables get updates
+with the values from the reloaded code.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H3><A NAME="Dynamically_updating_configurati">Dynamically updating configuration files</A></H3></CENTER>
+<P>
+The CGI script below allows a system administrator, to dynamically update
+configuration file through the web interface. Combining this with the code
+we have just showed to reload the modified files, you get a complete suite
+of dynamically reconfigurable system which doesn't require server restart
+and can be performed from any machine having just a web interface (a simple
+browser connected to the Internet).
+
+<P>
+Let's say you have a configuration file like:
+
+<P>
+<PRE> package MainConfig;
+
+ use strict;
+ use vars qw(%c);
+
+ %c = (
+ name => "Larry Wall",
+ release => "5.000",
+ comments => "Adding more ways to do the same thing :)",
+
+ other => "More config values",
+
+ hash => { foo => "bar",
+ fooo => "barr",
+ },
+
+ array => [qw( a b c)],
+
+ );
+</PRE>
+<P>
+You want to make the variables <CODE>name</CODE>, <CODE>release</CODE> and <CODE>comments</CODE>
+dynamically configurable. Which means that you want to have a web interface
+with input form that allows to modify these variables. Once modified you
+want to update the configuration file and propogate the changes to all the
+currently running processes. Quite a simple task.
+
+<P>
+Let's see the main stages of this algorithm. Create a form with preset
+current values of the variables. Let the administrator to modify and submit
+the changes. Validate that the submitted information is correctly formatted
+(numeric fields should carry numbers, literal - words and etc). Update the
+configuration file. Update the modified value in the memory of the current
+process. Present the form as before but with updated fields if any.
+
+<P>
+The only part that seems to be complicated to implement is a configuration
+file update. For a few reasons. If updating the file breaks it - the whole
+service wouldn't work. If the file is very big and includes comments and
+complex data structures, parsing the file can be quite a challenge.
+
+<P>
+So let's simplify the task. We wouldn't touch the original configuration
+file, if all we want is to updated a few variables, why don't we create a
+little configuration file with just a variables that can be modified
+throught the web interface and overwrite it each time there is something to
+be changed. This way we don't have to parse the file, before updating it.
+And if the main configuration file is going to be changed, we don't care
+about it -- since we aren't dependent on it any more.
+
+<P>
+Moreover, we will have these dynamically updated variables duplicated, they
+will show up in both places - in the main file and in the dynamic file. We
+do it, to simplify the maintainance. When a new release is being installed
+the dynamic configuration file shouldn't exist at all. It'll be created
+only after a first update. The only change it requires to the main code is
+to add a snippet of code to load this file if it exists and was changed as
+we just saw.
+
+<P>
+This additional code must be executed after the main configuration file is
+being loaded. That way the updated variables would override the default
+values in the main file.
+
+<P>
+META: extend on the comments:
+
+<P>
+<PRE> # remember to run this code under taint mode
+
+ use strict;
+ use vars qw($q %c $dynamic_config_file %vars_to_change %validation_rules);
+
+ use CGI ();
+
+ use lib qw(.);
+ use MainConfig ();
+ *c = \%MainConfig::c;
+
+ $dynamic_config_file = "./config.pl";
+
+ # load the dynamic conf file if exists, and override the default
+ # values from the main config file
+ do $dynamic_config_file if -e $dynamic_config_file and -r _;
+
+ # fields that can be changed and their titles
+ %vars_to_change =
+ (
+ 'name' => "Patch Pumkin's Name",
+ 'release' => "Current Perl Release",
+ 'comments' => "Release Comments",
+ );
+
+ %validation_rules =
+ (
+ 'name' => sub { $_[0] =~ /^[\w\s\.]+$/; },
+ 'release' => sub { $_[0] =~ /^\d+\.[\d_]+$/; },
+ 'comments' => sub { 1; },
+ );
+
+ $q = new CGI;
+ print $q->header(-type=>'text/html'),
+ $q->start_html();
+
+ my %updates = ();
+
+ # We always rewrite the dynamic config file, so we want all the
+ # vars to be passed but to save the time we will only do checking
+ # of vars that that was changed the rest will be retrieved from
+ # the 'prev_foo' values
+ foreach (keys %vars_to_change) {
+ # copy var so we can modify it
+ my $new_val = $q->param($_) || '';
+
+ # strip a possible ^M char (DOS/WIN)
+ $new_val =~ s/\cM//g;
+
+ # push to hash if was changed
+ $updates{$_} = $new_val
+ if defined $q->param("prev_".$_) and $new_val ne $q->param("prev_".$_);
+ }
+
+ # Notice that we cannot trust the previous values of the variables
+ # since they were presented to user as hidden form variables, and
+ # of course user can mangle those. In our case we don't care since
+ # it cannot make any damage, since as you will see in a minute we
+ # verify each variable by the rules we define.
+
+ # Process if there is something to process. Will be not called if
+ # it's invoked a first time to diplay the form or when the form
+ # was submitted but the values weren't modified (we know that by
+ # comparing with the previous values of the variables, which are
+ # the hidden fields in the form)
+
+ # process and update the values if valid
+ process_change_config(%updates) if %updates;
+
+ # print the update form
+ conf_modification_form();
+
+ # update the config file but first validate that the values are correct ones
+ #########################
+ sub process_change_config{
+ my %updates = @_; # dereference
+
+ # we will list here all the malformatted vars
+ my %malformatted = ();
+
+ print $q->b("Trying to validate these values<BR>");
+ foreach (keys %updates) {
+ print "<DT><B>$_</B> => <PRE>$updates{$_}</PRE>";
+
+ # now we have to handle each var to be changed very very carefully
+ # since this file goes immediately into production!
+ $malformatted{$_} = delete $updates{$_}
+ unless $validation_rules{$_}->($updates{$_});
+
+ } # end of foreach my $var (keys %updates)
+
+ # print warnings if there are any invalid changes
+ print $q->hr,
+ $q->p($q->b(qq{Warning! These variables were attempted to be
+ changed, but found malformed, thus the original
+ value will be preserved.})
+ ),
+ join(",<BR>",
+ map { $q->b($vars_to_change{$_}) . " : $malformatted{$_}\n"
+ } keys %malformatted)
+ if %malformatted;
+
+ # Now complete the vars that weren't changed from the
+ # $q->param('prev_var') values
+ map { $updates{$_} = $q->param('prev_'.$_) unless exists $updates{$_}
+ } keys %vars_to_change;
+
+ # Now we have all the data that should be written into dynamic
+ # config file
+
+ # escape single quotes "'" while creating a file
+ my $content = join "\n",
+ map { $updates{$_} =~ s/(['\\])/\\$1/g;
+ '$c{' . $_ . "} = '" . $updates{$_} . "';\n"
+ } keys %updates;
+
+ # now add '1;' to make require() happy
+ $content .= "\n1;";
+
+ # keep the dummy result in $r so it'll not complain
+ eval {my $res = $content};
+ if ($@) {
+ print qq{Warning! Something went wrong with config file
+ generation!<P> The error was : <BR><PRE>$@</PRE>};
+ return;
+ }
+
+ print $q->hr;
+
+ # overwrite the dynamic config file
+ use Symbol ();
+ my $fh = Symbol::gensym();
+ open $fh, ">$dynamic_config_file.bak"
+ or die "Can't open the $dynamic_config_file.bak for writing :$! \n";
+ flock $fh,2; # exclusive lock
+ seek $fh,0,2; # rewind to the start
+ truncate $fh, 0; # the file might shrink!
+ print $fh $content;
+ close $fh;
+
+ # OK, now we make a real file
+ rename "$dynamic_config_file.bak",$dynamic_config_file;
+
+ # rerun it to update variables in the current process! Note that
+ # it wouldn't update the variables in other processes. A special
+ # code that watches the timestamps on the config file will do this
+ # work for each process. Since the next invocation will update the
+ # configuration anyway, why do we need to load it here? The reason
+ # is simple, since we are going to fill form's input fields, with
+ # the updated data.
+ do $dynamic_config_file;
+
+ } # end sub process_change_config
+
+ ##########################
+ sub conf_modification_form{
+
+ print $q->center($q->h3("Update Form"));
+
+ print $q->hr,
+ $q->p(qq{This form allows you to dynamically update the current
+ configuration. You don\'t need to restart the server in
+ order for changes to take an effect}
+ );
+
+ # set the previous settings into the form's hidden fields, so we
+ # know whether we have to do some changes or not
+ map {$q->param("prev_$_",$c{$_}) } keys %vars_to_change;
+
+ # raws for the table, go into the form
+ my @configs = ();
+
+ # prepare one textfield entries
+ push @configs,
+ map {
+ $q->td(
+ $q->b("$vars_to_change{$_}:"),
+ ),
+ $q->td(
+ $q->textfield(-name => $_,
+ -default => $c{$_},
+ -override => 1,
+ -size => 20,
+ -maxlength => 50,
+ )
+ ),
+ } qw(name release);
+
+ # prepare multiline textarea entries
+ push @configs,
+ map {
+ $q->td(
+ $q->b("$vars_to_change{$_}:"),
+ ),
+ $q->td(
+ $q->textarea(-name => $_,
+ -default => $c{$_},
+ -override => 1,
+ -rows => 10,
+ -columns => 50,
+ -wrap => "HARD",
+ )
+ ),
+ } qw(comments);
+
+ print $q->startform('POST',$q->url),"\n",
+ $q->center($q->table(map {$q->Tr($_),"\n",} @configs),
+ $q->submit('','Update!'),"\n",
+ ),
+ map ({$q->hidden("prev_".$_, $q->param("prev_".$_))."\n" }
+ keys %vars_to_change), # hidden previous values
+ $q->br,"\n",
+ $q->endform,"\n",
+ $q->hr,"\n",
+ $q->end_html;
+
+ } # end sub conf_modification_form
+</PRE>
+<P>
+Once updated the script generates a file like:
+
+<P>
+<PRE> $c{release} = '5.6';
+
+ $c{name} = 'Gurusamy Sarathy';
+
+ $c{comments} = 'Perl rules the world!';
+
+ 1;
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Reloading_handlers">Reloading handlers</A></H2></CENTER>
+<P>
+If you want to reload perlhandler on each invocation, the following trick
+will do it:
+
+<P>
+<PRE> PerlHandler "sub { do 'MyTest.pm'; MyTest::handler(shift) }"
+</PRE>
+<P>
+<CODE>do()</CODE> will reload <CODE>MyTest.pm</CODE> every request.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Name_collisions_with_Modules_and">Name collisions with Modules and libs</A></H1></CENTER>
+<P>
+To make things clear before we go into details: each child process has its
+own <CODE>%INC</CODE> hash which is used to store information about its compiled modules. The
+keys of the hash are the names of the modules or parameters passed to <CODE>require()</CODE> (<CODE>use()</CODE>). The values are the full or relative paths to these modules/files. Let's
+say we have
+<CODE>my-lib.pl</CODE> and <CODE>MyModule.pm</CODE> both located at <CODE>/home/httpd/perl/my/</CODE>.
+
+<UL>
+<P><LI><STRONG><A NAME="item__home_httpd_perl_my_is_in_the_">/home/httpd/perl/my/ is in the @INC at the server startup.</A></STRONG>
+<P>
<PRE> require "my-lib.pl";
use MyModule.pm;
print $INC{"my-lib.pl"},"\n";
@@ -1740,9 +3283,7 @@
<PRE> my-lib.pl
MyModule.pm
</PRE>
-<P>
-* <CODE>/home/httpd/perl/my/</CODE> isn't in the <CODE>@INC</CODE> path at the server startup.
-
+<P><DT><STRONG><A NAME="item__home_httpd_perl_my_">/home/httpd/perl/my/ isn't in the @INC path at the server startup.</A></STRONG><DD>
<P>
<PRE> require "my-lib.pl";
use MyModule.pm;
@@ -1750,7 +3291,7 @@
print $INC{"MyModule.pm"},"\n";
</PRE>
<P>
-Wouldn't work, since perl cannot find the modules.
+wouldn't work, since perl cannot find the modules.
<P>
Adding <CODE>use lib</CODE>:
@@ -1769,8 +3310,9 @@
<PRE> my-lib.pl
MyModule.pm
</PRE>
+</UL>
<P>
-I'm talking about single server child below!
+I'm talking about single child below!
<P>
Let's look at 3 faulty script's name space related scenarios:
@@ -2002,7 +3544,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="More_package_name_related_issues">More package name related issues</A></H2></CENTER>
+<CENTER><H1><A NAME="More_package_name_related_issues">More package name related issues</A></H1></CENTER>
<P>
If you have the following:
@@ -2017,26 +3559,82 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H2></CENTER>
+<CENTER><H1><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H1></CENTER>
+<P>
+<CODE>Apache::Registry</CODE> scripts cannot contain <CODE>__END__</CODE> or <CODE>__DATA__</CODE>
+tokens.
+
+<P>
+Why? Because <CODE>Apache::Registry</CODE> scripts are being wrapped into a subroutine called <CODE>handler</CODE>, like the script at URI <CODE>/perl/test.pl</CODE>:
+
+<P>
+<PRE> print "Content-type: text/plain\n\n";
+ print "Hi";
+</PRE>
+<P>
+When the script is being executed under <CODE>Apache::Registry</CODE> handler, it actually becomes:
+
<P>
-<CODE>Apache::Registry</CODE> scripts cannot contain __END__ or __DATA__ tokens.
+<PRE> package Apache::ROOT::perl::test_2epl;
+ use Apache qw(exit);
+ sub handler {
+ print "Content-type: text/plain\n\n";
+ print "Hi";
+ }
+</PRE>
+<P>
+So if you happen to put an <CODE>__END__</CODE> tag, like:
+
+<P>
+<PRE> print "Content-type: text/plain\n\n";
+ print "Hi";
+ __END__
+ Some text that wouldn't be normally executed
+</PRE>
+<P>
+it will be turned into:
+
+<P>
+<PRE> package Apache::ROOT::perl::test_2epl;
+ use Apache qw(exit);
+ sub handler {
+ print "Content-type: text/plain\n\n";
+ print "Hi";
+ __END__
+ Some text that wouldn't be normally executed
+ }
+</PRE>
+<P>
+and you try to execute this script, you will receive the following warning:
+
+<P>
+<PRE> Missing right bracket at q line 4, at end of line
+</PRE>
+<P>
+And that's clear, Perl cuts everything after <CODE>__END__</CODE> tag. The same thing applies to <CODE>__DATA__</CODE> tag.
+
+<P>
+Also, rememeber that whatever applies to <CODE>Apache::Registry</CODE> scripts, in most cases applies to <CODE>Apache::PerlRun</CODE> scripts.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Output_from_system_calls">Output from system calls</A></H2></CENTER>
+<CENTER><H1><A NAME="Output_from_system_calls">Output from system calls</A></H1></CENTER>
<P>
Output of <CODE>system()</CODE>, <CODE>exec()</CODE>, and <CODE>open(PIPE,"|program")</CODE> calls will not be sent to the browser unless your Perl was configured with
<CODE>sfio</CODE>.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Using_format_">Using format()</A></H2></CENTER>
+<CENTER><H1><A NAME="Using_format_and_write_">Using format() and write()</A></H1></CENTER>
<P>
-Currently possible only if you have perl compiled with <CODE>sfio</CODE>.
+The Perl <CODE>tie()'d</CODE> filehandle interface is not complete,
+<CODE>format()</CODE> / <CODE>write()</CODE> are ones of the missing
+pieces. If you configure Perl with
+<CODE>sfio</CODE>, <CODE>write()</CODE> and <CODE>format()</CODE> should work just fine.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Using_exit_">Using exit()</A></H2></CENTER>
+<CENTER><H1><A NAME="Using_exit_">Using exit()</A></H1></CENTER>
<P>
Perl's <STRONG>exit()</STRONG> built-in function cannot be used in mod_perl scripts. Calling it causes the
server child to exit (which makes the whole idea of using mod_perl
@@ -2095,13 +3693,13 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Running_from_shell">Running from shell</A></H2></CENTER>
+<CENTER><H1><A NAME="Running_from_shell">Running from shell</A></H1></CENTER>
<P>
Your scripts <STRONG>will not</STRONG> run from the command line (yet) unless you use <CODE>CGI::Switch</CODE> or <CODE>CGI.pm</CODE> and perl 5.004+ and do not make any direct calls to <CODE>Apache-&gt;methods</CODE>.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="I_O_is_different">I/O is different</A></H2></CENTER>
+<CENTER><H1><A NAME="I_O_is_different">I/O is different</A></H1></CENTER>
<P>
If you are using Perl 5.004 or better, most CGI scripts can run under
mod_perl untouched. If you're using 5.003, Perl's built-in <CODE>read()</CODE>
@@ -2109,30 +3707,257 @@
<CODE>print()</CODE>.
<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Special_Perl_Variables">Special Perl Variables</A></H1></CENTER>
+<P>
+A special Perl variables like <CODE>$|</CODE> (buffering), <CODE>$^T</CODE> (time), <CODE>$^W</CODE>
+(warnings), <CODE>$/</CODE> (input record separator), <CODE>$\</CODE> (output record separator) and many more are all global variables. It means
+that you cannot localize them with <CODE>my().</CODE> Only
+<CODE>local()</CODE> is permitted to do that. Since the child server
+doesn't quit - if in one of your scripts you modify the global varible
+it'll be changed for the rest of the process' life and would affect all the
+scripts that will be executed under the same process.
+
+<P>
+Remembering this you should never write a code like this. We will exercise
+the input record separator variable. If you undefine this variable, a
+diamond operator will suck the whole file at once.
+
+<P>
+<PRE> $/ = undef;
+ open IN, "file" ....
+ # slurp it all inside a variable
+ $all_the_file = <IN>;
+</PRE>
+<P>
+The proper way is to have a <CODE>local()</CODE> keyword before the special
+variable is being changed, like:
+
+<P>
+<PRE> local $/ = undef;
+ open IN, "file" ....
+ # slurp it all inside a variable
+ $all_the_file = <IN>;
+</PRE>
+<P>
+But there is a little catch. <CODE>local()</CODE> will propogate the
+changed value to any of the code below it and would be in effect untill the
+script will be finished, if not modified in some other place.
+
+<P>
+A cleaner approach is to embrace the whole code that is being effected by
+the modificated variable in to a block, like:
+
+<P>
+<PRE> {
+ $/ = undef;
+ open IN, "file" ....
+ # slurp it all inside a variable
+ $all_the_file = <IN>;
+ }
+</PRE>
+<P>
+That way when Perl leaves the block, it restores the original value of the <CODE>$/</CODE> variable. So you should worry about this variable anywhere else in scope of
+your program.
+
+<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A></H2></CENTER>
+<CENTER><H1><A NAME="Generating_correct_HTTP_Headers">Generating correct HTTP Headers</A></H1></CENTER>
+<P>
+When writing your own handlers with Perl API the proper way to send the
+HTTP Header is to set the header first and then to send it. Like:
+
+<P>
+<PRE> $r->content_type('text/html');
+ $r->send_http_header;
+ return OK if $r->header_only;
+</PRE>
+<P>
+If the client issues a HTTP <CODE>HEAD</CODE> request rather than the usual
+<CODE>GET</CODE>, to be compilent with the HTTP protocol we better will not send the
+document body, but the the HTTP header only. When Apache receives a HEAD
+request, it sets <EM>header_only()</EM> to true. If we see that this has happened, we return from the handler
+immediately with an OK status code.
+
+<P>
+Generally, you don't need the explicit content type setting, since Apache
+does it for you, by looking up the MIME type of the request by matching the
+extension of the URI in the MIME tables (from the
+<CODE>mime.types</CODE> file). So if the request URI is <CODE>/welcome.html</CODE>, the
+<CODE>text/html</CODE> content-type will be picked. However for CGI scripts or URIs that cannot be
+mapped by a known extension, you should set the appropriate type by using <CODE>content_type()</CODE> method.
+
+<P>
+The situation is a little bit different with <CODE>Apache::Registry</CODE> and alike handlers. It means that if you take a basic CGI script like:
+
+<P>
+<PRE> print "Content-type: text/plain\n\n";
+ print "Hello world";
+</PRE>
<P>
-By default, mod_perl does not send any headers by itself, however, you may
-wish to change this (in <CODE>httpd.conf</CODE>):
+it wouldn't work, because the HTTP header will be not sent. By default,
+mod_perl does not send any headers by itself, however, you may wish to
+change this by adding:
<P>
<PRE> PerlSendHeader On
</PRE>
<P>
-Now the response line and common headers will be sent as they are by
-mod_cgi. And, just as with mod_cgi, <CODE>PerlSendHeader</CODE> will not send the MIME type and a terminating newline. Your script must
-send that itself, e.g.:
+in <CODE><Location</CODE>> part of your configuration. Now the response line and common headers
+will be sent as they are by mod_cgi. And, just as with mod_cgi, <CODE>PerlSendHeader</CODE> will not send the MIME type and a terminating double newline. Your script
+must send that itself, e.g.:
<P>
<PRE> print "Content-type: text/html\r\n\r\n";
</PRE>
+<P>
+Note, that the book always uses ``\n\n'' and not ``\r\n\r\n''. The latter
+is a way to send new lines as defined in HTTP standards, but as of this
+moment all the browsers accept the former format as well. To follow
+strictly the HTTP protocol you must you the ``\r\n'' format.
+
+<P>
+The <STRONG>PerlSendHeader On</STRONG> directive tells mod_perl to intercept anything that looks like a header
+line (such as <CODE>Content-Type:
+text/plain</CODE>) and automatically turn it into a correctly formatted HTTP/1.0 header, the
+same way it happens with CGI scripts running under mod_cgi. This allows you
+to keep your CGI scripts unmodified.
+
+<P>
+There is <CODE>$ENV{PERL_SEND_HEADER}</CODE> which tells whether
+<CODE>PerlSendHeader</CODE> is <CODE>On</CODE> or <CODE>Off</CODE>. You can use it in your module like:
+
+<P>
+<PRE> if($ENV{PERL_SEND_HEADER}) {
+ print "Content-type: text/html\n\n";
+ }
+ else {
+ my $r = Apache->request;
+ $r->content_type('text/html');
+ $r->send_http_header;
+ }
+</PRE>
+<P>
+If you use <EM>CGI.pm</EM>'s <EM>header()</EM> function to generate HTTP headers, you do not need to activate this
+directive because <EM>CGI.pm</EM> detects
+<EM>mod_perl</EM> and calls <EM>send_http_header()</EM> for you. However, it does not hurt to use this directive anyway.
+
+<P>
+There is no free lunch -- you get the mod_cgi behavior on cost of little
+but still overhead of parsing the text that is being sent, and mod_perl
+makes the assumption that individual headers are not split across print
+statements.
+
+<P>
+The <CODE>Apache::print()</CODE> routine has to gather up the headers that your script outputs, in order to
+pass them to <CODE>$r-&gt;send_http_header</CODE>. This happens in <CODE>src/modules/perl/Apache.xs</CODE> (<CODE>print</CODE>) and
+<CODE>Apache/Apache.pm</CODE> (<CODE>send_cgi_header</CODE>). There is a shortcut in there, namely the assumption that each print
+statement contains one or more complete headers. If for example you used to
+generate a
+<CODE>Set-Cookie</CODE> header by multiply <CODE>print()</CODE> statements, like:
+
+<P>
+<PRE> print "Content-type: text/html\n";
+ print "Set-Cookie: iscookietext\; ";
+ print "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
+ print "path=\/\; ";
+ print "domain=\.mmyserver.com\; ";
+ print "\n\n";
+ print "hello";
+</PRE>
+<P>
+your generated <CODE>Set-Cookie</CODE> header is split over a number of print statements and gets lost. The above
+example wouldn't work! Try this instead:
+
+<P>
+<PRE> print "Content-type: text/html\n";
+ my $cookie = "Set-Cookie: iscookietext\; ";
+ $cookie .= "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
+ $cookie .= "path=\/\; ";
+ $cookie .= "domain=\.mmyserver.com\; ";
+ print $cookie;
+ print "\n\n";
+ print "hello";
+</PRE>
+<P>
+Sometimes when you call a script you see an ugly <CODE>"Content-Type:
+text/html"</CODE> displayed at the top of the page, and of course the HTML code becomes
+broken. As you understand from the above discussion this generally happens
+when your code already send the header, that's why you see it rendered into
+a browser's page. This might happen when you call the <CODE>CGI.pm</CODE> <CODE>$q-&gt;header</CODE> method or mod_perl's
+<CODE>$r-&gt;send_http_header</CODE>.
+
+<P>
+If you have a complicated application where the header might be generated
+from many different places, depending on the calling logic, you might want
+to write a special subroutine that sends a header, and keeps a track
+whether the header has been already sent. Of course you can use a global
+variable to flag that the header has been already sent, but there is
+another elegant solution, where the closure effect is a desired feature.
+
+<P>
+Just copy the code below, including the block's curly braces. And
+everywhere in your code you print the header use the <CODE>print_header()</CODE>
+subroutine. <CODE>$need_header</CODE> is the same kind of beast as a static variable in C, so it remembers its
+value from call to call. The first time you will call the <CODE>print_header</CODE>, the value of <CODE>$need_header</CODE>
+will become zero and on the subsequent calls if any happens, the header
+will be not sent any more.
+
+<P>
+<PRE> {
+ my $need_header = 1;
+ sub print_header {
+ my type = shift || "text/html";
+ print("Content-type: $type\n\n),$need_header = 0 if $need_header;
+ }
+ }
+</PRE>
+<P>
+In your code you call the above subroutine as:
+
+<P>
+<PRE> print_header();
+</PRE>
+<P>
+or
+
+<P>
+<PRE> print_header("text/plain);
+</PRE>
+<P>
+if you want to override the default (text/html) MIME type.
+
+<P>
+Let's make our smart method to elaborate with PerlSendHeader directive
+settings, to always do the right thing. It's especially important if you
+write an application that you are going to distribute, hopefully as an Open
+Source.
+
+<P>
+<PRE> {
+ my $need_header = 1;
+ sub print_header {
+ my type = shift || "text/html";
+ return unless $need_header;
+ $need_header = 0;
+ if($ENV{PERL_SEND_HEADER}) {
+ print "Content-type: $type\n\n";
+ }
+ else {
+ my $r = Apache->request;
+ $r->content_type($type);
+ $r->send_http_header;
+ }
+ }
+ }
+</PRE>
<P>
-If you are using <CODE>CGI.pm</CODE> or <CODE>CGI::Switch</CODE> and <STRONG>print
-$q->header</STRONG> you do _not_ need <CODE>PerlSendHeader</CODE> On.
+You can continue to improve this subroutine even further to handle
+additional headers, like cookies and alike.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H2></CENTER>
+<CENTER><H1><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H1></CENTER>
<P>
To run a Non Parsed Header CGI script under mod_perl, simply add to your
code:
@@ -2141,8 +3966,7 @@
<PRE> local $| = 1;
</PRE>
<P>
-And if you normally set <CODE>PerlSendHeader On</CODE>, add this to your
-<CODE>httpd.conf</CODE>:
+And if you normally set <CODE>PerlSendHeader On</CODE>, add this to your server's configuration file:
<P>
<PRE> <Files */nph-*>
@@ -2151,7 +3975,7 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="BEGIN_blocks">BEGIN blocks</A></H2></CENTER>
+<CENTER><H1><A NAME="BEGIN_blocks">BEGIN blocks</A></H1></CENTER>
<P>
Perl executes <CODE>BEGIN</CODE> blocks during the compile time of code as soon as possible. The same is
true under mod_perl. However, since mod_perl normally only compiles scripts
@@ -2213,7 +4037,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="END_blocks">END blocks</A></H2></CENTER>
+<CENTER><H1><A NAME="END_blocks">END blocks</A></H1></CENTER>
<P>
As perlmod explains, an <CODE>END</CODE> subroutine is executed as late as possible, that is, when the interpreter
exits. In the mod_perl environment, the interpreter does not exit until the
@@ -2236,14 +4060,15 @@
<P>
All other <CODE>END</CODE> blocks encountered during other <CODE>Perl*Handler</CODE>
call-backs, e.g. <CODE>PerlChildInitHandler</CODE>, will be suspended while the process is running and called during <CODE>child_exit()</CODE> when the process is shutting down. Module authors might wish to use
-<CODE>$r-&gt;register_cleanup</CODE> as an alternative to <CODE>END</CODE> blocks if this behavior is not desirable.
+<CODE>$r-&gt;register_cleanup()</CODE> as an alternative to <CODE>END</CODE> blocks if this behavior is not desirable. <CODE>$r-&gt;register_cleanup()</CODE> is being called at the CleanUp processing phase of each request and thus
+can be used to emulate plain perl's <CODE>END{}</CODE> block behavior.
<P>
The last paragraph is very important for the <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Switches_w_T">Switches -w, -T</A></H2></CENTER>
+<CENTER><H1><A NAME="Switches_w_T">Switches -w, -T</A></H1></CENTER>
<P>
Normally when you run perl from the command line or have the shell invoke
it with `#!', you may choose to pass perl switch arguments such as <STRONG>-w</STRONG> or <STRONG>-T</STRONG>. Most command line arguments have a equivalent special variable. For
@@ -2281,7 +4106,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="strict_pragma">strict pragma</A></H2></CENTER>
+<CENTER><H1><A NAME="strict_pragma">strict pragma</A></H1></CENTER>
<P>
It's _absolutely_ mandatory (at least for development) to start all your
scripts with:
@@ -2306,7 +4131,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Turning_warnings_ON">Turning warnings ON</A></H2></CENTER>
+<CENTER><H1><A NAME="Turning_warnings_ON">Turning warnings ON</A></H1></CENTER>
<P>
Have a <CODE>local $^W=1</CODE> in the script or <CODE>PerlWarn ON</CODE> at the server configuration file. Turning the warning on will save you a
lot of troubles with debugging your code. Note that all perl switches, but
@@ -2347,7 +4172,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="diagnostics_pragma">diagnostics pragma</A></H2></CENTER>
+<CENTER><H1><A NAME="diagnostics_pragma">diagnostics pragma</A></H1></CENTER>
<P>
This is a Perl compiler pragma which forces verbose warning diagnostics.
Put at the start of your scripts:
@@ -2370,7 +4195,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A></H2></CENTER>
+<CENTER><H1><A NAME="Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A></H1></CENTER>
<P>
To pass an environment variable from a configuration file, add to it:
@@ -2398,7 +4223,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Global_Variables">Global Variables</A></H2></CENTER>
+<CENTER><H1><A NAME="Global_Variables">Global Variables</A></H1></CENTER>
<P>
It's always a good idea to stay away from global variables when possible.
Some variables must be global so Perl can see them, such as a module's <CODE>@ISA</CODE> or <CODE>$VERSION</CODE> variables (or fully qualified
@@ -2430,13 +4255,13 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A></H2></CENTER>
+<CENTER><H1><A NAME="Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A></H1></CENTER>
<P>
Files pulled in via <STRONG>use</STRONG> or <STRONG>require</STRONG> statements are not automatically reloaded when changed on disk. See <A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A> for more info.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Apache_and_syslog">Apache and syslog</A></H2></CENTER>
+<CENTER><H1><A NAME="Apache_and_syslog">Apache and syslog</A></H1></CENTER>
<P>
When native syslog support is enabled, the stderr stream will be redirected
to <CODE>/dev/null</CODE>!
@@ -2447,7 +4272,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Memory_leakage">Memory leakage</A></H2></CENTER>
+<CENTER><H1><A NAME="Memory_leakage">Memory leakage</A></H1></CENTER>
<P>
Scripts under mod_perl can very easily leak memory! Global variables stay
around indefinitely, lexical variables (declared with <CODE>my()</CODE> are destroyed when they go out of scope, provided there are no references
@@ -2733,176 +4558,6 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
-<P>
-When you develop plain CGI scripts, you can just change the code, and rerun
-the CGI from your browser. Since the script isn't cached in memory, the
-next time you call it the server starts up a new perl process, which
-recompiles it from scratch. The effects of any modifications you've applied
-are immediately present.
-
-<P>
-The situation is different with <CODE>Apache::Registry</CODE>, since the whole idea is to get maximum performance from the server. By
-default, the server won't spend the time to check whether any included
-library modules have been changed. It assumes that they weren't, thus
-saving a few milliseconds to <CODE>stat()</CODE> the source file (multiplied by however many modules/libraries you are <CODE>use()</CODE>-ing and/or <CODE>require()</CODE>-ing in your script.) The only check that is being done is whether your
-main script has been changed. So if you have only one script that doesn't
-<CODE>use()</CODE> (or <CODE>require()</CODE>) other perl modules (or packages), there is nothing new about it. If
-however, you are developing a script that includes other modules, the files
-you <CODE>use()</CODE> or <CODE>require()</CODE> aren't being checked whether they have been modified.
-
-<P>
-Acknowledging this, how do we get our modperl-enabled server to recognize
-changes in any library modules? Well, there are a couple of techniques:
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
-<P>
-The simplest approach is to restart the server each time you apply some
-change to your code. See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Using_Apache_StatINC">Using Apache::StatINC</A></H2></CENTER>
-<P>
-After restarting the server about 100 times, you will be tired and will
-look for another solutions. Help comes from the
-<CODE>Apache::StatINC</CODE> module.
-
-<P>
-<CODE>Apache::StatINC</CODE> reloads <CODE>%INC</CODE> files when updated on disk. When Perl pulls a file via require, it stores
-the filename in the global hash <CODE>%INC</CODE>. The next time Perl tries to require the same file, it sees the file in <CODE>%INC</CODE> and does not reload from disk. This module's handler iterates over <CODE>%INC</CODE> and reloads the file if it has changed on disk.
-
-<P>
-To enable this module just add two lines to <CODE>httpd.conf</CODE> file.
-
-<P>
-<PRE> PerlModule Apache::StatINC
- PerlInitHandler Apache::StatINC
-</PRE>
-<P>
-To be sure it really works, turn on the debug mode on your development box
-with <CODE>PerlSetVar StatINCDebug On</CODE>. You end up with something like:
-
-<P>
-<PRE> PerlModule Apache::StatINC
- <Location /perl>
- SetHandler perl-script
- PerlHandler Apache::Registry::handler
- Options ExecCGI
- PerlSendHeader On
- PerlInitHandler Apache::StatINC
- PerlSetVar StatINCDebug On
- </Location>
-</PRE>
-<P>
-Beware that only the modules located in <CODE>@INC</CODE> are being reloaded on change, and you can change the <CODE>@INC</CODE> only before the server has been started (in startup file).
-
-<P>
-Whatever you do in your scripts and modules which are being <CODE>required()</CODE> after the server startup will not have any effect on <CODE>@INC</CODE>. When you do:
-
-<P>
-<PRE> use lib qw(foo/bar);
-</PRE>
-<P>
-the <CODE>@INC</CODE> is being changed only for the time the code is being parsed and compiled.
-When it's over the <CODE>@INC</CODE> is being reset to its original value. To make sure that you have set a
-correct <CODE>@INC</CODE> fetch <A
-HREF="http://www.nowhere.com/perl-status?inc">http://www.nowhere.com/perl-status?inc</A>
-and look at the bottom of the page. (I assume you have configured the <A HREF="././config.html#_perl_status_location">/perl-status location</A>.)
-
-<P>
-Also, notice the following caveat: While ``<CODE>.</CODE>'' is in the <CODE>@INC</CODE> -- perl knows to <CODE>require()</CODE> files relative to the script directory. Once the script was parsed - the
-server doesn't remember the path any more! So you end up with broken entry
-in <CODE>%INC</CODE> like:
-
-<P>
-<PRE> $INC{bar.pl} eq "bar.pl"
-</PRE>
-<P>
-If you want Apache::StatINC to reload your script - modify the <CODE>@INC</CODE>
-at the server startup file! or use a full path in <CODE>require()</CODE> call.
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Reloading_only_specific_files">Reloading only specific files</A></H2></CENTER>
-<P>
-Checking all the modules in <STRONG>%INC</STRONG> every time can add a large overhead to server response times, and you
-certainly would not want
-<CODE>Apache::StatINC</CODE> module to be enabled in your production site's configuration. But sometimes
-you want to have some Configuration module to be reloaded without
-restarting the whole server. To accomplish this, one of the solutions is to
-use a code that I describe below.
-
-<P>
-Assuming that you start your script with loading <CODE>Foo::Bar</CODE> and importing some tags:
-
-<P>
-<PRE> use lib "/some/private/path";
- use Foo::Bar qw(:tags_group tag1 tag2);
-</PRE>
-<P>
-Now to make a modification testing and reload at runtime you have to use
-something like this:
-
-<P>
-<PRE> # child's private global variable to keep the timestamps
- use vars qw(%MODIFIED);
-
- my $module = "Foo::Bar";
-
- (my $inc_key = $module) =~ s|::|/|g;
- $inc_key .= ".pm";
- # the $module's path should be registered in %INC if it was already loaded
- my $path = $INC{$inc_key} or warn "Can't find $inc_key in %INC\n";
-
- # Note: consider to not continue if $path wasn't set!
-
- # set modification time if it wasn't set before (first time)
- # Note: Use (stat $path)[9] instead of -M test, if you reset
- # time with $^M=time
- $MODIFIED{$module} ||= -M $path;
-
- # now check whether it was changed (assuming the above wasn't
- # performed in this session
- if ($MODIFIED{$module} != -M $path){
- # only if deleted from %INC the require will be called below
- delete $INC{$inc_key};
-
- require $path;
-
- # now reimport the symbols (if you need them back :)
- import $module qw(:tags_group tag1 tag2);
-
- # Update the MODIFICATION times
- $MODIFIED{$module} = -M $path;
- }
-</PRE>
-<P>
-You may want to add debug print statements to debug this code in your
-application.
-
-<P>
-Read the ``use versus require'' article for more info. ( <A
-HREF="http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require">http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require</A>
-)
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Reloading_handlers">Reloading handlers</A></H2></CENTER>
-<P>
-If you want to reload perlhandler on each invocation, the following trick
-will do it:
-
-<P>
-<PRE> PerlHandler "sub { do 'MyTest.pm'; MyTest::handler(shift) }"
-</PRE>
-<P>
-<CODE>do()</CODE> will reload <CODE>MyTest.pm</CODE> every request.
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A></H1></CENTER>
<P>
When you write a script running under mod_cgi, you can get away with sloppy
@@ -3067,6 +4722,40 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Sharing_variables_between_proces">Sharing variables between processes</A></H1></CENTER>
+<P>
+META: to be completed
+
+<UL>
+<P><LI>
+<P>
+Global variables initialized at the server startup, through the Perl
+startup file, can be shared between processes, untill modified by some of
+the processes. e.g. when you write:
+
+<P>
+<PRE> $My::debug = 1;
+</PRE>
+<P>
+all processes will read the same value. If one of the processes changes
+that value to <CODE>0</CODE>, it'll be still equal to <CODE>1</CODE> for any process, but the one who actually did the change. When the process
+modifies the variable, it becomes process' private copy.
+
+<P><LI>
+<P>
+<CODE>IPC::Shareable</CODE> can be used to share variables between children.
+
+<P><LI>
+<P>
+libmm
+
+<P><LI>
+<P>
+other methods?
+
+</UL>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A></H1></CENTER>
<P>
To trap all/most Perl run-time errors and send the output to the client
@@ -3272,23 +4961,27 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A></H1></CENTER>
+<CENTER><H1><A NAME="Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A></H1></CENTER>
<P>
Generally you should not fork from your mod_perl scripts, since when you do
-- you are forking the entire apache web server, lock, stock and barrel.
Not only is your perl code being duplicated, but so is mod_ssl,
mod_rewrite, mod_log, mod_proxy, mod_spelling or whatever modules you have
-used in your server, all the core routines and so on. A much wiser approach
-would be to spawn a sub-process, hand it the information it needs to do the
-task, and have it detach (close x3 +
+used in your server, all the core routines and so on.
+
+<P>
+A much wiser approach would be to spawn a sub-process, hand it the
+information it needs to do the task, and have it detach (close x3 +
<CODE>setsid()</CODE>). This is wise only if the parent who spawns this process, immediately
-continue, you do not wait for the sub process to complete. This approach is
+continue, you do not wait for the sub-process to complete. This approach is
suitable for a situation when you want to trigger a long time taking
process through the web interface, like processing some data, sending email
to thousands of subscribed users and etc. Otherwise, you should convert the
code into a module, and use its functions or methods to call from CGI
-script. Just making a
-<CODE>system()</CODE> call defeats the whole idea behind mod_perl, perl interpreter and modules
+script.
+
+<P>
+Just making a <CODE>system()</CODE> call defeats the whole idea behind mod_perl, perl interpreter and modules
should be loaded again for this external program to run.
<P>
@@ -3329,54 +5022,96 @@
post-processing, look into <CODE>PerlCleanupHandler</CODE>.
<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A></H1></CENTER>
+If you are interested in more deep level details, this is what actually
+happens when you fork and make a system call, like
+
<P>
-The <CODE>Apache::print()</CODE> routine has to gather up the headers that your script outputs, in order to
-pass them to <CODE>$r-&gt;send_http_header</CODE>. This happens in <CODE>src/modules/perl/Apache.xs</CODE> (<CODE>print</CODE>) and
-<CODE>Apache/Apache.pm</CODE> (<CODE>send_cgi_header</CODE>). There is a shortcut in there, namely the assumption that each print
-statement contains one or more complete headers. If for example you used to
-generate a
-<CODE>Set-Cookie</CODE> header by multiply <CODE>print()</CODE> statements, like:
+<PRE> system("echo Hi"),exit unless fork();
+</PRE>
+<P>
+What happens is that <CODE>fork()</CODE> gives you 2 execution paths and
+the child gets virtual memory sharing a copy of the program text (read
+only) and sharing a copy of the data space copy-on-write (remember why you
+pre-load modules in mod_perl?). In the above code a parent will immediately
+continue with the code that comes up after the fork, while the forked
+process will execute <CODE>system("echo Hi")</CODE> and then terminate itself. Note that you might need to set:
<P>
-<PRE> print "Content-type: text/html\n";
- print "Set-Cookie: iscookietext\; ";
- print "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
- print "path=\/\; ";
- print "domain=\.mmyserver.com\; ";
- print "\n\n";
- print "hello";
+<PRE> $SIG{CHLD} = sub {wait};
</PRE>
<P>
-your generated <CODE>Set-Cookie</CODE> header is split over a number of print statements and gets lost. Try this:
+or
<P>
-<PRE> print "Content-type: text/html\n";
- my $cookie = "Set-Cookie: iscookietext\; ";
- $cookie .= "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
- $cookie .= "path=\/\; ";
- $cookie .= "domain=\.mmyserver.com\; ";
- print $cookie;
- print "\n\n";
- print "hello";
+<PRE> $SIG{CHLD} = IGNORE;
+</PRE>
+<P>
+or the terminated process might become a zombie. Normally, every process
+has its parent, many processes a children of PID 1, the init process.
+Zombie, is a process that doesn't have a father. When the child quits, it
+reports the termination to his parent. If he doesn't know who the father is
+it becomes zombie. (META: Did I formulate it correctly?)
+
+<P>
+The only work is setting up the page tables for the virtual memory and the
+second process goes on its separate way.
+
+<P>
+Next, Perl will find <CODE>/bin/echo</CODE> along the search path, and invoke it directly. Perl <CODE>system()</CODE>
+is *not* <CODE>system(3)</CODE> [C-library]. Only when the command has shell meta-chars does Perl invoke a
+real shell. That's a *very* nice optimization.
+
+<P>
+Only if you do:
+
+<P>
+<PRE> system "sh -c 'echo foo'"
</PRE>
+<P>
+OS actually parses your command with a shell so you <CODE>exec()</CODE> a
+copy of
+<CODE>/bin/sh</CODE>, but since one is almost certainly already running somewhere, the system
+will notice that (via the disk inode reference) and replace your virtual
+memory page table with one pointed at the already-loaded program code plus
+your own data space. Then the shell parses the passed command.
+
<P>
-<META> some leftovers... # =head1 Coding with mod_perl
+Since it is <CODE>echo</CODE>, it will execute it as a built-in in the latter example or a <CODE>/bin/echo</CODE> in the former and be done, but this is only an example. You aren't calling <CODE>system("echo Hi")</CODE> in your mod_perl scripts, right? Since most other real things (heavy
+programs executed as a subprocess) would involve repeating the process to
+load the specified command or script (it might involve some actual demand
+paging from the program file if you execute new code).
+<P>
+The only place you see real overhead from this scheme is when the parent
+process is huge (unfortunately like mod_perl...) and the page table becomes
+large as a side effect. The whole point of mod_perl is to avoid having to
+<CODE>fork()</CODE> / <CODE>exec()</CODE> something on every hit, though.
+Perl can do just about anything by itself. However, you probably won't get
+in trouble until you hit about 30 forks/sec on a so-so pentium.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A></H1></CENTER>
+<P>
+Let's say that you wrote a few handlers to process a request, and they all
+need to share some custom Perl data structure. The <CODE>pnotes()</CODE>
+method comes to rescue. Taken that one of the handlers stored some data in
+hash <CODE>%my_data</CODE>, before it finished its activity:
+
+<P>
+<PRE> # First handler:
+ $r->pnotes('my_info' => \%hash);
+</PRE>
<P>
-Before you start coding for <CODE>Apache::Registry</CODE>, you have to change your programming state of mind. Scripts running under
-mod_perl are like subroutines are being called from a continually running
-daemon. Imagine a daemon process that when requested to process some
-script, reads it in, compiles it as a subroutine, and finally executes it.
-On any subsequent request, it'll just recall the already compiled
-subroutine. Hope that you get the idea.
+All the following handler will be able to retrive the stored data with.
<P>
-The best thing you do when coding from scratch is to make it clean and use
-packages. By ``make it clean'' we mean make certain that you <STRONG>use
-strict;</STRONG> and that your script produces no warnings when tested via
-<STRONG>perl -cw myscript.pl</STRONG>. As you go thru the notes you will understand why. </META>
+<PRE> # Later handler:
+ my $info = $r->pnotes('my_info');
+ print $info->{foo};
+</PRE>
+<P>
+The stored information will be destroyed at the end of the request.
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
@@ -3388,6 +5123,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="start.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -3401,7 +5146,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/17/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
@@ -3463,6 +5208,8 @@
<LI><A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>
<LI><A HREF="#Avoid_Importing_Functions">Avoid Importing Functions</A>
+ <LI><A HREF="#PerlSetupEnv_Off">PerlSetupEnv Off</A>
+ <LI><A HREF="#_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A>
<LI><A HREF="#Shared_Memory">Shared Memory</A>
<LI><A HREF="#Checking_script_modification_tim">Checking script modification times</A>
<LI><A HREF="#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
@@ -3510,6 +5257,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Performance_The_Overall_picture">Performance: The Overall picture</A></H1></CENTER>
@@ -3641,6 +5397,21 @@
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A></H2></CENTER>
<P>
+(META: while the numbers and conclusions are mostly correct, need to
+rewrite the whole benchmark section using the GTop library to report the
+shared memory which is very important and will improve the benchmarks)
+
+<P>
+(META: Add the memory size tests when the server was compiled with
+EVERYTHING=1 and without it, does loading everything imposes a big change
+in the memory footprint? Probably the suggestion would be as follows: For a
+development server use EVERYTHING=1, while for a production if your server
+is pretty busy and/or low on memory and every bit is on account, only the
+required parts should be built in. BTW, remember that apache comes with
+many modules that are being built by default, and you might not need
+those!)
+
+<P>
I have conducted a few tests to benchmark the memory usage when some
modules are preloaded. The first set of tests checks the memory use with
Library Perl Module preload (only <CODE>CGI.pm</CODE>). The second set checks the compile method of <CODE>CGI.pm</CODE>. The third test checks the benefit of Library Perl Module preload but a
@@ -3850,8 +5621,24 @@
root 26792 0.0 0.0 3124 1440 - A 17:19:21 0:00 httpd
httpd 91052 0.0 1.0 6568 5040 - A 17:19:21 0:00 httpd
</PRE>
+<P>
+Observation: child httpd has grown by 3276K. Ouch: 512K more!!!
+
+<P>
+The reason is that when you preload at the startup all of the methods, they
+all are being precompiled, there are many of them and they take a big chunk
+of memory. If you don't use the <CODE>compile()</CODE> method, only the
+functions that are being used will be compiled. Yes, it will slightly slow
+down the first reposnse of each process, but the actuall memory usage will
+be lower. BTW, if you write in the script:
+
+<P>
+<PRE> use CGI qw(all);
+</PRE>
<P>
-Observation: child httpd has grown by 3276K. Great difference: 512K less!!!
+Only the symbols of all functions are being imported. While they are taking
+some space, it's smaller than the space that a compiled code of these
+functions might occupy.
<P>
<STRONG>Server restarted</STRONG>
@@ -3961,6 +5748,52 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="PerlSetupEnv_Off">PerlSetupEnv Off</A></H1></CENTER>
+<P>
+<CODE>PerlSetupEnv Off</CODE> is another optimization you might consider.
+
+<P>
+<EM>mod_perl</EM> fiddles with the environment to make it appear as if the script were being
+called under the CGI protocol. For example, the
+<CODE>$ENV{QUERY_STRING}</CODE> environment variable is initialized with the contents of <EM>Apache::args()</EM>, and <CODE>$ENV{SERVER_NAME}</CODE> is filled in from the value returned by <EM>Apache::server_hostname()</EM>.
+
+<P>
+But <CODE>%ENV</CODE> population is expensive. Those who have moved to the Perl Apache API no
+longer need this extra <CODE>%ENV</CODE> population, can gain by turning it <STRONG>Off</STRONG>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A></H1></CENTER>
+<P>
+Newer Perl versions also have build time options to reduce runtime memory
+consumption. These options might shrink down the size of your httpd by
+about ~150k (quite big number if you remember to multiply it by the number
+of chidren you use.)
+
+<P>
+<CODE>-DTWO_POT_OPTIMIZE</CODE> macro improves allocations of data with size close to a power of two; but
+this works for big allocations (starting with 16K by default). Such
+allocations are typical for big hashes and special-purpose scripts,
+especially image processing.
+
+<P>
+Perl memory allocation is by bucket with sizes close to powers of two.
+Because of these malloc overhead may be big, especially for data of size
+exactly a power of two. If <CODE>PACK_MALLOC</CODE> is defined, perl uses a slightly different algorithm for small allocations
+(up to 64 bytes long), which makes it possible to have overhead down to 1
+byte for allocations which are powers of two (and appear quite often).
+
+<P>
+Expected memory savings (with 8-byte alignment in <CODE>alignbytes</CODE>) is about 20% for typical Perl usage. Expected slowdown due to additional
+malloc overhead is in fractions of a percent (hard to measure, because of
+the effect of saved memory on speed).
+
+<P>
+You will find these and other memory improvement details in
+<CODE>perl5004delta.pod</CODE>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Shared_Memory">Shared Memory</A></H1></CENTER>
<P>
You've probably noticed that the word shared is being repeated many times
@@ -4061,6 +5894,10 @@
<CODE>Apache::Status</CODE> now includes a new StatusLexInfo option.
<P>
+Apache::Leak works better if you've built a libperld.a (see SUPPORT) and
+given PERL_DEBUG=1 to mod_perl's Makefile.PL
+
+<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Limiting_the_size_of_the_process">Limiting the size of the processes</A></H1></CENTER>
<P>
@@ -5183,7 +7020,8 @@
<PRE> PerlModule Apache::DBI
</PRE>
<P>
-It is important, to load this module before any other <CODE>ApacheDBI*</CODE> module!
+It is important, to load this module before any other <CODE>DBI</CODE>,
+<CODE>DBD::*</CODE> and <CODE>ApacheDBI*</CODE> modules!
<P>
<PRE> db.pl
@@ -5221,6 +7059,11 @@
that child process. See the <CODE>Apache::DBI</CODE> manpage to see the requirements for this method.
<P>
+You can also benefit from persistent connections by replacing
+<CODE>prepare()</CODE> with <CODE>prepare_cached().</CODE> But it can
+produce a little overhead (META, why?).
+
+<P>
Another problem is with timeouts: some databases disconnect the client
after a certain time of inactivity. This problem is known as <STRONG>morning
bug</STRONG>. The <CODE>ping()</CODE> method ensures that this will not happen. Some
@@ -5421,6 +7264,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="porting.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -5434,7 +7287,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/16/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
@@ -5509,6 +7362,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Do_it_like_me_">Do it like me?!</A></H1></CENTER>
@@ -6143,6 +8005,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="performance.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -6255,6 +8127,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A></H1></CENTER>
@@ -6274,7 +8155,7 @@
% perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
DO_HTTPD=1 USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
% make && make test && make install
- % cd ../apache_x.x.x/src
+ % cd ../apache_x.x.x
% make install
</PRE>
<P>
@@ -6345,7 +8226,7 @@
directory tree and to put the <CODE>httpd</CODE> there.
<P>
-<PRE> % cd ../apache_x.x.x/src
+<PRE> % cd ../apache_x.x.x
% make install
</PRE>
<P>
@@ -7412,6 +9293,14 @@
coming from, before changing the <CODE>remote_ip</CODE>.
<P>
+Generally you shouldn't trust the <CODE>X-Forwarded-For</CODE> header. You only want to rely on <CODE>X-Forwarded-For</CODE> headers from proxies you control yourself. If you know how to spoof a
+cookie you've probably got the general idea on making HTTP headers and can
+spoof the
+<CODE>X-Forwarded-For</CODE> header as well. The only address *you* can count on as being a reliable
+value is the one from
+<CODE>r-&gt;connection-&gt;remote_ip</CODE>.
+
+<P>
From that point on, the remote IP address is correct. You should be able to
access <CODE>REMOTE_ADDR</CODE> as usual.
@@ -7463,6 +9352,10 @@
The only possible caveat in the config file is that your <CODE>Auth</CODE> stuff needs to be in <CODE><Directory ...</CODE>> ... <CODE></Directory</CODE>> tags because if you use a <CODE><Location /...</CODE>> ... <CODE></Location</CODE>> the proxypass server takes the auth info for its own authentication
and would not pass it on.
+<P>
+The same with mod_ssl, if plugged into a front-end server, all the SSL
+requests be encoded/decoded properly by it.
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
@@ -7473,6 +9366,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="strategy.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="install.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -7486,7 +9389,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/17/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
@@ -7557,15 +9460,18 @@
</UL>
<LI><A HREF="#Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A>
+ <LI><A HREF="#Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A>
<LI><A HREF="#Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A>
<LI><A HREF="#Server_Installation_problems">Server Installation problems</A>
<UL>
+ <LI><A HREF="#_skipping_test_on_this_plat">......skipping test on this platform</A>
<LI><A HREF="#make_test_fails">make test fails</A>
<LI><A HREF="#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
<LI><A HREF="#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
</UL>
+ <LI><A HREF="#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
</UL>
<!-- INDEX END -->
@@ -7582,6 +9488,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Configuration_and_Installation">Configuration and Installation</A></H1></CENTER>
@@ -7852,6 +9767,25 @@
for more information on local perl installations.
<P>
+So you end up with something like:
+
+<P>
+<PRE> $ gunzip <apache_x.x.xx.tar.gz | tar xvf -
+ $ gunzip <mod_perl-x.xx.tar.gz | tar xvf -
+ $ cd mod_perl-x.xx
+ $ perl Makefile.PL \
+ APACHE_SRC=../apache-1.3.X/src \
+ DO_HTTPD=1 \
+ USE_APACI=1 \
+ EVERYTHING=1 \
+ APACI_ARGS=--sbindir=/home/stas/sbin/httpd_perl, \
+ --sysconfdir=/home/stas/etc/httpd_perl, \
+ --localstatedir=/home/stas/var/httpd_perl, \
+ --runtimedir=/home/stas/var/httpd_perl/run, \
+ --logfiledir=/home/stas/var/httpd_perl/logs, \
+ --proxycachedir=/home/stas/var/httpd_perl/proxy
+</PRE>
+<P>
You will not be able to have the server listen to a port lower then 1024 if
you are not starting it as <CODE>root</CODE>, so choose a port number above 1024. (I use 8080 in most cases). Note that
you will have to use a URL like <CODE>http://www.nowhere.com:8080</CODE> in that case, but that is not a problem since usually users do not directly
@@ -7890,6 +9824,17 @@
</UL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A></H1></CENTER>
+<P>
+Sure, you can take a look at the symbols inside the httpd executable. e.g.
+if you want to see whether you have enabled PERL_AUTH=1 while building the
+mod_perl, you do:
+
+<P>
+<PRE> nm httpd | grep perl_authenticate
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A></H1></CENTER>
<P>
It is possible to determine which options were given to modperl's
@@ -7924,6 +9869,56 @@
<CENTER><H1><A NAME="Server_Installation_problems">Server Installation problems</A></H1></CENTER>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="_skipping_test_on_this_plat">......skipping test on this platform</A></H2></CENTER>
+<P>
+While doing <CODE>make test</CODE> you would notice that some of the tests are being reported as skipped. The
+real reason is that you are missing some optional modules for these test to
+be passed. For a hint you might want to peek at the content of each test
+(you will find them all in the <CODE>./t</CODE> directory (mnemonic - t, tests). I'll list a few examples, but of course
+the requirements might be changed in the future.
+
+<P>
+> modules/cookie......skipping test on this platform
+
+<P>
+install libapreq
+
+<P>
+> modules/psections...skipping test on this platform
+
+<P>
+install Devel::Symdump / Data::Dumper
+
+<P>
+> modules/request.....skipping test on this platform
+
+<P>
+libapreq
+
+<P>
+> modules/sandwich....skipping test on this platform
+
+<P>
+Apache::Sandwich
+
+<P>
+> modules/stage.......skipping test on this platform
+
+<P>
+Apache::Stage
+
+<P>
+> modules/symbol......skipping test on this platform
+
+<P>
+Devel::Symdump
+
+<P>
+Chances are that all of these are installed if you use <CODE>CPAN.pm</CODE> to
+<CODE>install Bundle::Apache</CODE>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="make_test_fails">make test fails</A></H2></CENTER>
<P>
There are two configuration parameters: <CODE>PREP_HTTPD</CODE> and <CODE>DO_HTTPD</CODE>, that you can use in:
@@ -7984,6 +9979,54 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="mod_auth_dbm_nuances">mod_auth_dbm nuances</A></H1></CENTER>
+<P>
+If you are a user of <STRONG>mod_auth_dbm</STRONG> or <STRONG>mod_auth_db</STRONG>, you may need to edit Perl's <CODE>Config</CODE> module. When Perl is configured it attempts to find libraries for ndbm,
+gdbm, db, etc., for the *DBM*_File modules. By default, these libraries are
+linked with Perl and remembered by the <STRONG>Config</STRONG> module. When mod_perl is configured with apache, the <STRONG>ExtUtils::Embed</STRONG> module returns these libraries to be linked with httpd so Perl extensions
+will work under mod_perl. However, the order in which these libraries are
+stored in
+<STRONG>Config.pm</STRONG>, may confuse <CODE>mod_auth_db*</CODE>. If <CODE>mod_auth_db*</CODE> does not work with mod_perl, take a look at this order with the following
+command:
+
+<P>
+<PRE> % perl -V:libs
+</PRE>
+<P>
+If <CODE>-lgdbm</CODE> or <CODE>-ldb</CODE> is before <CODE>-lndbm</CODE>, example:
+
+<P>
+<PRE> libs='-lnet -lnsl_s -lgdbm -lndbm -ldb -ldld -lm -lc -lndir -lcrypt';
+</PRE>
+<P>
+Edit <STRONG>Config.pm</STRONG> and move <CODE>-lgdbm</CODE> and <CODE>-ldb</CODE> to the end of the list. Here's how to find <STRONG>Config.pm</STRONG>:
+
+<P>
+<PRE> % perl -MConfig -e 'print "$Config{archlibexp}/Config.pm\n"'
+</PRE>
+<P>
+Another solution for building Apache/mod_perl+mod_auth_dbm under Solaris is
+to remove the DBM and NDBM ``emulation'' from libgdbm.a. Seems Solaris
+already provides its own DBM and NDBM, and there's no reason to build GDBM
+with them (for us anyway).
+
+<P>
+In our Makefile for GDBM, we changed
+
+<P>
+<PRE> OBJS = $(DBM_OF) $(NDBM_OF) $(GDBM_OF)
+</PRE>
+<P>
+to
+
+<P>
+<PRE> OBJS = $(GDBM_OF)
+</PRE>
+<P>
+Rebuild libgdbm, then Apache/mod_perl.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A></H1></CENTER>
<P>
Since most of the functionality that various apache mod_* modules provide
@@ -8003,6 +10046,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="scenario.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="config.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -8016,7 +10069,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/09/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
@@ -8073,6 +10126,14 @@
<LI><A HREF="#Alias_Configurations">Alias Configurations</A>
<LI><A HREF="#Location_Configuration">Location Configuration</A>
+ <LI><A HREF="#PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A>
+ <LI><A HREF="#Perl_Handlers">Perl*Handlers</A>
+ </UL>
+
+ <LI><A HREF="#STACKED_HANDLERS">STACKED HANDLERS</A>
+ <LI><A HREF="#PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A>
+ <UL>
+
<LI><A HREF="#PerlFreshRestart">PerlFreshRestart</A>
<LI><A HREF="#_perl_status_location">/perl-status location</A>
<UL>
@@ -8107,12 +10168,13 @@
<LI><A HREF="#My_script_works_under_cgi_bin_b">My script works under cgi-bin, but when called via mod_perl I see A 'Save-As' prompt</A>
<LI><A HREF="#Is_there_a_way_to_provide_a_diff">Is there a way to provide a different startup.pl file for each individual virtual host</A>
<LI><A HREF="#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A>
- <LI><A HREF="#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with</A>
+ <LI><A HREF="#A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A>
<LI><A HREF="#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
</UL>
<LI><A HREF="#Configuration_Security_Concerns">Configuration Security Concerns</A>
<LI><A HREF="#Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A>
+ <LI><A HREF="#Apache_restarts_twice_on_start">Apache restarts twice on start</A>
</UL>
<!-- INDEX END -->
@@ -8128,6 +10190,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="mod_perl_Specific_Configuration">mod_perl Specific Configuration</A></H1></CENTER>
@@ -8238,8 +10309,8 @@
invocation. You will want to turn this off for nph (non-parsed-headers)
scripts. <CODE>PerlSendHeader On</CODE> means to call
<CODE>ap_send_http_header()</CODE> after parsing your script headers. It is only meant for CGI emulation, its
-always better to use <CODE>CGI-</CODE>header> from
-<CODE>CGI.pm</CODE> module or <CODE>$r-&gt;send_http_header</CODE> directly.
+always better to use <CODE>CGI-&gt;header</CODE>
+from <CODE>CGI.pm</CODE> module or <CODE>$r-&gt;send_http_header</CODE> directly.
<P>
Remember the <STRONG>Alias</STRONG> from the section above? We must use the same
@@ -8277,6 +10348,350 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A></H2></CENTER>
+<P>
+You may load modules from the config file at server startup via:
+
+<P>
+<PRE> PerlModule Apache::DBI CGI DBD::Mysql
+</PRE>
+<P>
+There is a limit of 10 <CODE>PerlModule</CODE>'s, if you need more to be loaded when the server starts, use one <CODE>PerlModule</CODE> to pull in many or write them all in a regular perl syntax and put them
+into a startup file which can be loaded with use of the <CODE>PerlRequire</CODE> directive.
+
+<P>
+<PRE> PerlRequire /home/httpd/perl/lib/startup.pl
+</PRE>
+<P>
+Both <CODE>PerlModule</CODE> and <CODE>PerlRequire</CODE> are implemented by <CODE>require(),</CODE> but there is a subtle change. <CODE>PerlModule</CODE> works like <CODE>use(),</CODE> expecting a module name without <CODE>.pm</CODE> extension and slashes.
+<CODE>Apache::DBI</CODE> is OK, while <CODE>Apache/DBI.pm</CODE> is not. <CODE>PerlRequire</CODE> is the opposite to <CODE>PerlModule</CODE> -- it expects a relative or full path to the module or a filename, like in
+the example above.
+
+<P>
+As with any file that's being <CODE>required()</CODE> -- it must return a <STRONG>true</STRONG>
+value, to ensure that this happens don't forget to add <CODE>1;</CODE> at the end of such files.
+
+<P>
+We must stress that all the code that is run at the server initialization
+time is run with root priveleges if you are executing it as a root user
+(you have to unless you choose an unpriveledged port, above 1024.
+somethings that you might have to if you don't have a root access. Just
+remember that you better pick a well known port like 8000 or 8080 since
+other non-standard ports might be blocked by firewalls that protect many
+organizations and individuals). This means that anyone who has write access
+to a script or module that is loaded by <CODE>PerlModule</CODE> or <CODE>PerlRequire</CODE>, effectively has root access to the system. You might want to take a look
+at the new and experimental <CODE>PerlOpmask</CODE> directive and <CODE>PERL_OPMASK_DEFAULT</CODE>
+compile time option to try to disable some dangerous operators.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Perl_Handlers">Perl*Handlers</A></H2></CENTER>
+<P>
+As you know Apache specifies about 11 phases of the request loop, namely in
+that order: Post-Read-Request, URI Translation, Header Parsing, Access
+Control, Authentication, Authorization, MIME type checking, FixUp, Response
+(Content phase). Logging and finally Cleanup. These are the stages of a
+request where the Apache API allows a module to step in and do something.
+There is a dedicated PerlHandler for each of these stages. Namely:
+
+<P>
+<PRE> PerlChildInitHandler
+ PerlPostReadRequestHandler
+ PerlInitHandler
+ PerlTransHandler
+ PerlHeaderParserHandler
+ PerlAccessHandler
+ PerlAuthenHandler
+ PerlAuthzHandler
+ PerlTypeHandler
+ PerlFixupHandler
+ PerlHandler
+ PerlLogHandler
+ PerlCleanupHandler
+ PerlChildExitHandler
+</PRE>
+<P>
+The first 4 handlers cannot be used in the <CODE><Location</CODE>>,
+<CODE><Directory</CODE>>, <CODE><Files</CODE>> and <CODE>.htaccess</CODE> file, the main reason is all the above require a known path to the file in
+order to bind a requested path with one or more of the identifiers above.
+Starting from <CODE>PerlHeaderParserHandler</CODE> (5th) URI is allready being mapped to a physical pathname, thus can be used
+to match the <CODE><Location</CODE>>,
+<CODE><Directory</CODE>> or <CODE><Files</CODE>> configuration section, or to look at
+<CODE>.htaccess</CODE> file if exists at the specified directory in the translated path.
+
+<P>
+The Apache documentation (or even better -- the ``Writing Apache Modules
+with Perl and C'' book by Doug MacEachern and Lincoln Stein) will tell you
+all about those stages and what your modules can do. By default, these
+hooks are disabled at compile time, see the INSTALL document for
+information on enabling these hooks.
+
+<P>
+Note that by default Perl API expects a subrotine called <CODE>handler</CODE> to handle the request in the registered PerlHandler module. Thus if your
+module implements this subrotine, you can register the handler as simple as
+writing:
+
+<P>
+<PRE> Perl*Handler Apache::SomeModule
+</PRE>
+<P>
+replace <EM>Perl*Handler</EM> with a wanted name of the handler. mod_perl will preload the specified
+module for you. But if you decide to give the handler code a different
+name, like <CODE>my_handler</CODE>, you must preload the module and to write explicitly the chosen name.
+
+<P>
+<PRE> PerlModule Apache::SomeModule
+ Perl*Handler Apache::SomeModule::my_handler
+</PRE>
+<P>
+Please note that the former approach will not preload the module at the
+startup, so either explicitly preload it with <CODE>PerlModule</CODE>
+directive, add it to the startup file or use a nice shortcut the
+<CODE>Perl*Handler</CODE> syntax suggests:
+
+<P>
+<PRE> Perl*Handler +Apache::SomeModule
+</PRE>
+<P>
+Notice the leading <CODE>+</CODE> character. It's equal to:
+
+<P>
+<PRE> PerlModule Apache::SomeModule
+ Perl*Handler Apache::SomeModule
+</PRE>
+<P>
+If a module wishes to know what handler is currently being run, it can find
+out with the <EM>current_callback</EM> method. This method is most useful to <EM>PerlDispatchHandlers</EM> who wish to only take action for certain phases.
+
+<P>
+<PRE> if($r->current_callback eq "PerlLogHandler") {
+ $r->warn("Logging request");
+ }
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="STACKED_HANDLERS">STACKED HANDLERS</A></H1></CENTER>
+<P>
+With the mod_perl stacked handlers mechanism, it is possible for more than
+one <CODE>Perl*Handler</CODE> to be defined and run during each stage of a request.
+
+<P>
+Perl*Handler directives can define any number of subroutines, e.g. (in
+config files)
+
+<P>
+<PRE> PerlTransHandler OneTrans TwoTrans RedTrans BlueTrans
+</PRE>
+<P>
+With the method, <CODE>Apache-&gt;push_handlers()</CODE>, callbacks can be added to the stack by scripts at runtime by mod_perl
+scripts.
+
+<P>
+<CODE>Apache-&gt;push_handlers()</CODE> takes the callback hook name as its first argument and a subroutine name or
+reference as its second. e.g.:
+
+<P>
+<PRE> Apache->push_handlers("PerlLogHandler", \&first_one);
+
+ $r->push_handlers("PerlLogHandler", sub {
+ print STDERR "__ANON__ called\n";
+ return 0;
+ });
+</PRE>
+<P>
+After each request, this stack is cleared out.
+
+<P>
+All handlers will be called unless a handler returns a status other than <CODE>OK</CODE> or <CODE>DECLINED</CODE>.
+
+<P>
+example uses:
+
+<P>
+<CODE>CGI.pm</CODE> maintains a global object for its plain function interface. Since the
+object is global, it does not go out of scope, DESTROY is never called. <CODE>CGI-&gt;new</CODE> can call:
+
+<P>
+<PRE> Apache->push_handlers("PerlCleanupHandler", \&CGI::_reset_globals);
+</PRE>
+<P>
+This function will be called during the final stage of a request,
+refreshing <CODE>CGI.pm</CODE>'s globals before the next request comes in.
+
+<P>
+<CODE>Apache::DCELogin</CODE> establishes a DCE login context which must exist for the lifetime of a
+request, so the <CODE>DCE::Login</CODE> object is stored in a global variable. Without stacked handlers, users must
+set
+
+<P>
+<PRE> PerlCleanupHandler Apache::DCELogin::purge
+</PRE>
+<P>
+in the configuration files to destroy the context. This is not
+``user-friendly''. Now, <CODE>Apache::DCELogin::handler</CODE> can call:
+
+<P>
+<PRE> Apache->push_handlers("PerlCleanupHandler", \&purge);
+</PRE>
+<P>
+Persistent database connection modules such as <CODE>Apache::DBI</CODE> could push a <CODE>PerlCleanupHandler</CODE> handler that iterates over <CODE>%Connected</CODE>, refreshing connections or just checking that ones have not gone stale.
+Remember, by the time we get to <CODE>PerlCleanupHandler</CODE>, the client has what it wants and has gone away, we can spend as much time
+as we want here without slowing down response time to the client (but the
+process is unavailable for serving new request befor the operation is
+completed).
+
+<P>
+<CODE>PerlTransHandlers</CODE> may decide, based on URI or other condition, whether or not to handle a
+request, e.g. <CODE>Apache::MsqlProxy</CODE>. Without stacked handlers, users must configure:
+
+<P>
+<PRE> PerlTransHandler Apache::MsqlProxy::translate
+ PerlHandler Apache::MsqlProxy
+</PRE>
+<P>
+<CODE>PerlHandler</CODE> is never actually invoked unless <CODE>translate()</CODE> sees the request is a proxy request (<CODE>$r-&gt;proxyreq</CODE>), if it is a proxy request, <CODE>translate()</CODE> sets <CODE>$r-&gt;handler("perl-script")</CODE>, only then will <CODE>PerlHandler</CODE> handle the request. Now, users do not have to specify <CODE>PerlHandler Apache::MsqlProxy</CODE>, the <CODE>translate()</CODE>
+function can set it with <CODE>push_handlers()</CODE>.
+
+<P>
+Includes, footers, headers, etc., piecing together a document, imagine (no
+need for SSI parsing!):
+
+<P>
+<PRE> PerlHandler My::Header Some::Body A::Footer
+</PRE>
+<P>
+A little test:
+
+<P>
+<PRE> #My.pm
+ package My;
+</PRE>
+<P>
+<PRE> sub header {
+ my $r = shift;
+ $r->content_type("text/plain");
+ $r->send_http_header;
+ $r->print("header text\n");
+ }
+ sub body { shift->print("body text\n") }
+ sub footer { shift->print("footer text\n") }
+ 1;
+ __END__
+</PRE>
+<P>
+<PRE> #in config
+ <Location /foo>
+ SetHandler "perl-script"
+ PerlHandler My::header My::body My::footer
+ </Location>
+</PRE>
+<P>
+Parsing the output of another PerlHandler? this is a little more tricky,
+but consider:
+
+<P>
+<PRE> <Location /foo>
+ SetHandler "perl-script"
+ PerlHandler OutputParser SomeApp
+ </Location>
+
+ <Location /bar>
+ SetHandler "perl-script"
+ PerlHandler OutputParser AnotherApp
+ </Location>
+</PRE>
+<P>
+Now, OutputParser goes first, but it <CODE>untie()'s</CODE> <CODE>*STDOUT</CODE> and re-tie()'s to its own package like so:
+
+<P>
+<PRE> package OutputParser;
+</PRE>
+<P>
+<PRE> sub handler {
+ my $r = shift;
+ untie *STDOUT;
+ tie *STDOUT => 'OutputParser', $r;
+ }
+
+ sub TIEHANDLE {
+ my($class, $r) = @_;
+ bless { r => $r}, $class;
+ }
+
+ sub PRINT {
+ my $self = shift;
+ for (@_) {
+ #do whatever you want to $_
+ $self->{r}->print($_ . "[insert stuff]");
+ }
+ }
+</PRE>
+<P>
+<PRE> 1;
+ __END__
+</PRE>
+<P>
+To build in this feature, configure with:
+
+<P>
+<PRE> % perl Makefile.PL PERL_STACKED_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
+</PRE>
+<P>
+Another method <CODE>Apache-&gt;can_stack_handlers</CODE> will return TRUE if mod_perl was configured with <CODE>PERL_STACKED_HANDLERS=1</CODE>, FALSE otherwise.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A></H1></CENTER>
+<P>
+If a Perl*Handler is prototyped with <CODE>$$</CODE>, this handler will be invoked as method. e.g.
+
+<P>
+<PRE> package My;
+ @ISA = qw(BaseClass);
+
+ sub handler ($$) {
+ my($class, $r) = @_;
+ ...;
+ }
+
+ package BaseClass;
+
+ sub method ($$) {
+ my($class, $r) = @_;
+ ...;
+ }
+ __END__
+</PRE>
+<P>
+Configuration:
+
+<P>
+<PRE> PerlHandler My
+</PRE>
+<P>
+or
+
+<P>
+<PRE> PerlHandler My->handler
+</PRE>
+<P>
+Since the handler is invoked as a method, it may inherit from other
+classes:
+
+<P>
+<PRE> PerlHandler My->method
+</PRE>
+<P>
+In this case, the <CODE>My</CODE> class inherits this method from <CODE>BaseClass</CODE>.
+
+<P>
+To build in this feature, configure with:
+
+<P>
+<PRE> % perl Makefile.PL PERL_METHOD_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="PerlFreshRestart">PerlFreshRestart</A></H2></CENTER>
<P>
To reload <CODE>PerlRequire</CODE>, <CODE>PerlModule</CODE>, other <CODE>use()</CODE>'d modules and flush the <CODE>Apache::Registry</CODE> cache on server restart, add:
@@ -8385,6 +10800,9 @@
<EM>ENVironment</EM> variables to your scripts. you can access them in your scripts through <CODE>%ENV</CODE> (e.g. <CODE>$ENV{"key"}</CODE>).
<P>
+Regarding the setting of <CODE>PerlPassEnv PERL5LIB</CODE> in httpd.conf If you turn on taint checks (<CODE>PerlTaintMode On</CODE>), <CODE>$ENV{PERL5LIB}</CODE> will be ignored (unset).
+
+<P>
<CODE>PerlSetVar</CODE> is very similar to <CODE>PerlSetEnv</CODE>, but you extract it with another method. In <Perl> sections:
<P>
@@ -8733,11 +11151,25 @@
You can watch how have you configured the <CODE><Perl</CODE>> sections through the <A HREF="././config.html#_perl_status_location">/perl-status</A> location, by choosing the <STRONG>Perl Sections</STRONG> from the menu.
<P>
-<A
-HREF="http://www.modperl.com/book/chapters/ch8.html#Debugging_B_E_lt_PerlE_gt_Sect">http://www.modperl.com/book/chapters/ch8.html#Debugging_B_E_lt_PerlE_gt_Sect</A>
-shows how can you dump the contents of your <CODE><Perl</CODE>> sections to the error_log.
+You can dump the configuration by <CODE><Perl</CODE>> sections configuration this way:
+
+<P>
+<PRE> <Perl>
+ use Apache::PerlSections();
+ ...
+ print STDERR Apache->PerlSections->dump();
+ </Perl>
+</PRE>
+<P>
+Alternatively you can store it in a file:
<P>
+<PRE> Apache::PerlSections->store("httpd_config.pl");
+</PRE>
+<P>
+You can then <CODE>require()</CODE> that file in some other <CODE><Perl</CODE>> section.
+
+<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</A></H1></CENTER>
<P>
@@ -8930,8 +11362,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with
-the same path from the second virtual host</A></H2></CENTER>
+<CENTER><H2><A NAME="A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A></H2></CENTER>
<P>
This has been a bug before, last fixed in 1.15_01, i.e. if you are running
1.15, that could be the problem. You should set this variable in a startup
@@ -8945,7 +11376,8 @@
script running for more than one Virtual host on the same machine, this can
be a waste, right? Set it to 0 in a startup script if you want to turn it
off and have this bug as a feature. (Only makes sense if you are sure that
-there will be no <STRONG>other</STRONG>scripts named by the same path/name)
+there will be no <STRONG>other</STRONG>scripts named by the same path/name). It also saves you some memory on the
+way.
<P>
<PRE> $Apache::Registry::NameWithVirtualHost = 0;
@@ -9014,6 +11446,19 @@
<P>
Note that you cannot have <CODE>Files</CODE> derective inside <CODE>Location</CODE>, but you can have <CODE>Files</CODE> inside <CODE>Directory</CODE>.
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Apache_restarts_twice_on_start">Apache restarts twice on start</A></H1></CENTER>
+<P>
+When the server is restarted. the configuration and module initialization
+phases are called again (twice in total). To ensure that the future restart
+will workout correctly, Apache actually runs these two phases twice during
+server startup, to check that all modules can survive a restart.
+
+<P>
+(META: And add an example that writes to the log file - I was restarted 1,
+2 times)
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
@@ -9024,6 +11469,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="install.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="frequent.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -9037,7 +11492,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/15/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
@@ -9107,6 +11562,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
@@ -9142,6 +11606,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="config.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -9232,6 +11706,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Restarting_techniques">Restarting techniques</A></H1></CENTER>
@@ -10131,6 +12614,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="frequent.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -10228,6 +12721,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
@@ -10584,6 +13086,17 @@
<P>
Also note that since the server is running in single mode, if the output
+returns HTML with <CODE><IMG</CODE>> tags, then the load of these will take a lot of time.
+
+<P>
+When you use Netscape client while your server is running in single-process
+mode, if the output returns a HTML with <CODE><IMG</CODE>> tags, then the load of these will take a lot of time, since the <CODE>KeepAlive</CODE>
+feature gets in the way. Netscape tries to open multiple connections and
+keep them open. Because there is only one server process listening, each
+connection has to time-out before the next succeeds. Turn off <CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect.
+
+<P>
+Also note that since the server is running in single mode, if the output
returns HTML with <CODE><IMG</CODE>> tags, then the load of these will take a lot of time. If you use
Netscape while your server is running in single-process mode, HTTP's <CODE>KeepAlive</CODE> feature gets in the way. Netscape tries to open multiple connections and
keep them open. Because there is only one server process listening, each
@@ -10862,6 +13375,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="control.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -10875,7 +13398,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/07/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
@@ -10946,6 +13469,7 @@
<LI><A HREF="#RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A>
<LI><A HREF="#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
<LI><A HREF="#server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A>
+ <LI><A HREF="#syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near "line arguments:"</A>
</UL>
<!-- INDEX END -->
@@ -10961,6 +13485,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="General_Advice">General Advice</A></H1></CENTER>
@@ -11286,8 +13819,8 @@
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A></H1></CENTER>
<P>
-Not all Perl modules can survive a reload. PerlFreshRestart does not much
-more than:
+Unfortunately, not all perl modules are robust enough to survive reload,
+for them, unusual situation. PerlFreshRestart does not much more than:
<P>
<PRE> while (my($k,$v) = each %INC) {
@@ -11309,6 +13842,20 @@
<P>
See <A HREF="././performance.html#Choosing_MaxClients">Choosing MaxClients</A>.
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near "line arguments:"</A></H1></CENTER>
+<P>
+<PRE> syntax error at /dev/null line 1, near "line arguments:"
+ Execution of /dev/null aborted due to compilation errors.
+ parse: Undefined error: 0
+</PRE>
+<P>
+There is a chance that your <CODE>/dev/null</CODE> device is broken. Try:
+
+<P>
+<PRE> % sudo echo > /dev/null
+</PRE>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
@@ -11319,6 +13866,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="obvious.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -11332,7 +13889,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/09/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
@@ -11394,7 +13951,8 @@
<LI><A HREF="#Authentication_code_snippets">Authentication code snippets</A>
<UL>
- <LI><A HREF="#Forcing_reauthenticating">Forcing reauthenticating</A>
+ <LI><A HREF="#Forcing_re_authentication">Forcing re-authentication</A>
+ <LI><A HREF="#OK_AUTH_REQUIRED_and_FORBIDDEN_">OK, AUTH_REQUIRED.and FORBIDDEN in Authentication handlers</A>
</UL>
</UL>
@@ -11412,6 +13970,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="An_Importance_of_Your_site_s_Sec">An Importance of Your site's Security</A></H1></CENTER>
@@ -11586,22 +14153,77 @@
<CENTER><H1><A NAME="Authentication_code_snippets">Authentication code snippets</A></H1></CENTER>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Forcing_reauthenticating">Forcing reauthenticating</A></H2></CENTER>
+<CENTER><H2><A NAME="Forcing_re_authentication">Forcing re-authentication</A></H2></CENTER>
<P>
To force authenticated user to reauthenticate just send the following
header to the browser:
<P>
-<PRE> HTTP/1.0 401 Unauthorized
+<PRE> WWW-Authenticate: Basic realm="My Realm"
+ HTTP/1.0 401 Unauthorized
</PRE>
<P>
-This will pop-up (on Netscape at least) a window saying that the
+This will pop-up (in Netscape at least) a window saying that the
<STRONG>Authorization Failed. Retry?</STRONG> And an <STRONG>OK</STRONG> and a <STRONG>Cancel</STRONG> buttons. When that window pops up you know that the password has been
cleared. If the user hits the <STRONG>Cancel</STRONG> button the username will also be cleared, and you can have a page that will
be output written after the header if this is a CGI (or PHP, or anything
else like that). If the user hits the <STRONG>OK</STRONG> button, the authentication window will be brought up again with their
previous username already in the username field.
+<P>
+In Perl API you would use <CODE>note_basic_auth_failure()</CODE> method to
+force reauthentication.
+
+<P>
+Since the browser's behaviour is in no way guaranteed, it also may not
+work, and that should be noted.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="OK_AUTH_REQUIRED_and_FORBIDDEN_">OK, AUTH_REQUIRED.and FORBIDDEN in Authentication handlers</A></H2></CENTER>
+<P>
+When your authentication handler returns OK, it means that user has
+correctly authenticated and now <CODE>$r-&gt;connection-&gt;user</CODE> will have the username set for all the subsequent requests. For
+<CODE>Apache::Registry</CODE> and friends, where the environment variables setting weren't turned off, an
+equivalent <CODE>$ENV{REMOTE_USER}</CODE>
+variable will be available. Password is available only through Perl API
+with help of <CODE>get_basic_auth_pw()</CODE> method.
+
+<P>
+If there is a failure, returned <CODE>AUTH_REQUIRED</CODE> flag will tell the browser to pop up an authentication window, to try
+again, unless it's a first time. For example:
+
+<P>
+<PRE> my($status, $sent_pw) = $r->get_basic_auth_pw;
+ unless($r->connection->user and $sent_pw) {
+ $r->note_basic_auth_failure;
+ $r->log_reason("Both a username and password must be provided");
+ return AUTH_REQUIRED;
+ }
+</PRE>
+<P>
+Let's say that you have a mod_perl authen handler, where user credentials
+are checked against a database, and it either returns
+<CODE>OK</CODE> or <CODE>AUTH_REQUIRED</CODE>. One of the possible authentication failure case might happen when the
+username/password are correct, but the user's account has been suspended
+temporarily.
+
+<P>
+If this is the case you would like to make the user aware of this, through
+a page display instead of having the browser pop up the auth dialog again.
+At the same time you need to refuse the authentication, of course.
+
+<P>
+The solution is to return <CODE>FORBIDDEN</CODE>, but before that you should set a custom error page for this specific
+handler, with help of
+<CODE>$r-&gt;custom_response</CODE>. Something like:
+
+<P>
+<PRE> use Apache::Constants qw(:common);
+ $r->custom_response(SERVER_ERROR, "/errors/suspended_account.html");
+
+ return FORBIDDEN if $suspended;
+</PRE>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
@@ -11612,6 +14234,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="warnings.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -11625,7 +14257,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/29/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
@@ -11721,6 +14353,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Why_Relational_SQL_Databases">Why Relational (SQL) Databases</A></H1></CENTER>
@@ -12832,6 +15473,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="security.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="dbm.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -12917,6 +15568,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Where_and_Why_to_use_dbm_files">Where and Why to use dbm files</A></H1></CENTER>
@@ -13115,7 +15775,7 @@
BEGIN {
# RCS/CVS complient: must be all one line, for MakeMaker
- $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.16 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
+ $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.17 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
}
@@ -13265,7 +15925,8 @@
A simple tie, READ lock and untie
<P>
-<PRE> my %mydb = ();
+<PRE> my $dbfile = "/tmp/test";
+ my %mydb = ();
my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
print $mydb{'stas'} if exists $mydb{'stas'};
# sync and untie
@@ -13292,7 +15953,8 @@
Perform both, read and write operations:
<P>
-<PRE> my %mydb = ();
+<PRE> my $dbfile = "/tmp/test";
+ my %mydb = ();
my $db = new DB_File::Wrap \%mydb, $dbfile;
print $mydb{'stas'} if exists $mydb{'stas'};
@@ -13322,6 +15984,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="databases.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="multiuser.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -13335,7 +16007,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/09/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
@@ -13404,6 +16076,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="ISPs_providing_mod_perl_services">ISPs providing mod_perl services - a fantasy or reality.</A></H1></CENTER>
@@ -13440,6 +16121,14 @@
user (guest books, counters and etc - the same standard scripts ISPs
providing since they were born). So you have to say <STRONG>NO</STRONG> for this choice.
+<P>
+More things to think about are file permissions (any user who is allowed to
+write and run CGI script, can at least read if not write any other files
+that has a permissions of the web server. This has nothing to do with
+mod_perl, and there are solutions for that
+<CODE>suEXEC</CODE> and <CODE>cgiwrap</CODE> for example) and <CODE>Apache::DBI</CODE> connections (You can pick a connection from the pool of cached
+connenctions, opened by someone else by hacking the <CODE>Apache::DBI</CODE> code).
+
<P><LI>
<P>
But, hey why I cannot let my user to run his own server, so I clean my
@@ -13568,7 +16257,7 @@
<P>
-<A HREF="././config.html#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with the same path from the second virtual host</A>
+<A HREF="././config.html#A_Script_from_one_virtual_host_c">Sometimes the script from one virtual host calls a script with the same path from the second virtual host</A>
@@ -13582,6 +16271,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="dbm.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="status.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -13595,7 +16294,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/09/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
@@ -13670,6 +16369,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Watching_the_server">Watching the server</A></H1></CENTER>
@@ -13768,6 +16476,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="multiuser.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -13841,6 +16559,8 @@
<LI><A HREF="#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
<LI><A HREF="#Monitoring_error_log_file">Monitoring error_log file</A>
<LI><A HREF="#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
+ <LI><A HREF="#Spinning_httpds">Spinning httpds</A>
+ <LI><A HREF="#PROFILING">PROFILING</A>
<LI><A HREF="#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
<LI><A HREF="#Devel_Peek">Devel::Peek</A>
</UL>
@@ -13858,6 +16578,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A></H1></CENTER>
@@ -14023,7 +16752,7 @@
<P>
Current perl implementation does not restore the original apache's C
handler when you use <CODE>local $SIG{FOO}</CODE> clause. While save/restore of
-<CODE>$SIG{ALRM}</CODE> was fixed in the mod_perl 1.19_01 (CVS version) other signals are not yet
+<CODE>$SIG{ALRM}</CODE> was fixed in the mod_perl 1.19_01 (CVS version), other signals are not yet
fixed. The real fix should probably be in Perl itself.
<P>
@@ -14059,6 +16788,9 @@
die $@ if $@;
</PRE>
<P>
+If a timeout happens and <CODE>SIGALRM</CODE> is thrown, the <CODE>alarm()</CODE> will be reset, otherwise <CODE>alarm 0</CODE> is reached and timer is being reset as well.
+
+<P>
Now you would write:
<P>
@@ -14073,6 +16805,49 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Spinning_httpds">Spinning httpds</A></H1></CENTER>
+<P>
+To see where an httpd is ``spinning'', try adding this to your script or a
+startup file:
+
+<P>
+<PRE> use Carp ();
+ $SIG{'USR1'} = sub {
+ Carp::confess("caught SIGUSR1!");
+ };
+</PRE>
+<P>
+Then issue the command line:
+
+<P>
+<PRE> kill -USR1 <spinning_httpd_pid>
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="PROFILING">PROFILING</A></H1></CENTER>
+<P>
+It is possible to profile code run under mod_perl with the
+<CODE>Devel::DProf</CODE> module available on CPAN. However, you must have apache version 1.3b3 or
+higher and the <CODE>PerlChildExitHandler</CODE>
+enabled. When the server is started, <CODE>Devel::DProf</CODE> installs an
+<CODE>END</CODE> block to write the <CODE>tmon.out</CODE> file, which will be run when the server is shutdown. Here's how to start
+and stop a server with the profiler enabled:
+
+<P>
+<PRE> % setenv PERL5OPT -d:DProf
+ % httpd -X -d `pwd` &
+ ... make some requests to the server here ...
+ % kill `cat logs/httpd.pid`
+ % unsetenv PERL5OPT
+ % dprofpp
+</PRE>
+<P>
+See also: <CODE>Apache::DProf</CODE>
+
+
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="examples_of_strace_or_truss_us">examples of strace (or truss) usage</A></H1></CENTER>
<P>
(META: below are some snippets of strace outputs from list's emails)
@@ -14174,6 +16949,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="status.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="browserbugs.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -14187,7 +16972,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/17/1999
+ <BR>Last Modified at 09/22/1999
</FONT>
</B>
</TD>
@@ -14256,6 +17041,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Preventing_QUERY_STRING_from_get">Preventing QUERY_STRING from getting corrupted because of &entity key names.</A></H1></CENTER>
@@ -14295,6 +17089,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="debug.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="modules.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -14383,6 +17187,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Apache_Session_Maintain_sessi">Apache::Session - Maintain session state across HTTP requests</A></H1></CENTER>
@@ -14646,6 +17459,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="browserbugs.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="perl.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -14737,6 +17560,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
@@ -15025,6 +17857,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="modules.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="snippets.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -15090,8 +17932,6 @@
<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
- <LI><A HREF="#Sending_MIME_headers">Sending MIME headers</A>
- <LI><A HREF="#How_to_avoid_printing_the_header">How to avoid printing the header more than once</A>
<LI><A HREF="#More_on_relative_paths">More on relative paths</A>
<LI><A HREF="#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server</A>
<LI><A HREF="#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
@@ -15110,49 +17950,18 @@
Amazon.com</a>.
<HR>
-
- <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<P>
-<CENTER><H1><A NAME="Sending_MIME_headers">Sending MIME headers</A></H1></CENTER>
-<P>
-By default, mod_perl does not send any headers by itself, however, you may
-wish to change this behavior by setting in the config file:
-
-<P>
-<PRE> PerlSendHeader On
-</PRE>
-<P>
-The safest bet is to use CGI.pm's <CODE>header()</CODE> method. (If you do <CODE>print header();</CODE>, you don't need the above setting.)
-<P>
-Also there is <CODE>$ENV{PERL_SEND_HEADER}</CODE> to see if <CODE>PerlSendHeader</CODE> is <CODE>On</CODE> or
-<CODE>Off</CODE>.
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="How_to_avoid_printing_the_header">How to avoid printing the header more than once</A></H1></CENTER>
-<P>
-I'm sure you have been in situations where you wish you knew whether the
-MIME header has already been printed. Since if it is printed again it will
-cause an ugly ``Content-type: ...'' string to show up in the browser. So
-how do we solve it? With the help of a closure.
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
-<P>
-Just copy the code below, including the block's curly parentheses. And
-everywhere in your code you print the header use the <CODE>print_header()</CODE> sub.
-<CODE>$need_header</CODE> is the same kind of beast as a static variable in C, so it remembers its
-value from call to call.
+ <HR>
+ <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
-<PRE> {
- my $need_header = 1;
- sub print_header {
- print header(@_),$need_header = 0 if $need_header;
- }
- }
-</PRE>
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="More_on_relative_paths">More on relative paths</A></H1></CENTER>
<P>
Many people use relative paths for <CODE>require</CODE>, <CODE>use</CODE>, etc., or open files in the current directory or relative to the current
@@ -15348,6 +18157,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="perl.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -15361,7 +18180,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/17/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
@@ -15453,6 +18272,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Is_it_important_">Is it important?</A></H1></CENTER>
@@ -15847,6 +18675,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="snippets.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="advocacy.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -15929,6 +18767,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Thoughts_about_scalability_and_f">Thoughts about scalability and flexibility</A></H1></CENTER>
@@ -16005,6 +18852,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="hardware.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -16093,6 +18950,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="READ_ME_FIRST">READ ME FIRST</A></H1></CENTER>
@@ -16125,8 +18991,11 @@
However, you are welcome to submit corrections and suggestions directly to
me at <A
HREF="mailto:sbekman@iname.com?subject=mod_perl%20guide%20corrections.">sbekman@iname.com?subject=mod_perl%20guide%20corrections.</A>
- <STRONG>But PLEASE
-NO QUESTIONS, they will be immediately deleted.</STRONG>
+If you are going to <STRONG>submit heavy corrections of the text</STRONG> (I love those!), please help me by downloading the source pages in POD
+(from the main age under the index) and directly editing them. I will use
+Emacs Ediff to perform an easy merge of your changes. Thank you! <STRONG>But PLEASE NO
+PERSONAL QUESTIONS, I didn't invite those by writing a guide. They all
+will be immediately deleted.</STRONG>
@@ -16215,11 +19084,47 @@
HREF="http://forum.swarthmore.edu/epigone/modperl">http://forum.swarthmore.edu/epigone/modperl</A>
. We owe it to Ken Williams.
+<P>
+More archives available:
+
+<UL>
+<P><LI>
<P>
-Another arhive: <A
+<A
HREF="http://www.geocrawler.com/lists/3/web/182/0/">http://www.geocrawler.com/lists/3/web/182/0/</A>
+<P><LI>
+<P>
+<A
+HREF="http://www.bitmechanic.com/mail-archives/modperl/">http://www.bitmechanic.com/mail-archives/modperl/</A>
+
+
+<P><LI>
+<P>
+<A
+HREF="http://www.mail-archive.com/modperl%40apache.org/">http://www.mail-archive.com/modperl%40apache.org/</A>
+
+
+<P><LI>
+<P>
+<A
+HREF="http://www.davin.ottawa.on.ca/archive/modperl/">http://www.davin.ottawa.on.ca/archive/modperl/</A>
+
+
+<P><LI>
+<P>
+<A
+HREF="http://www.progressive-comp.com/Lists/?l=apache-modperl&r=1&w=2#apache-modperl">http://www.progressive-comp.com/Lists/?l=apache-modperl&r=1&w=2#apache-modperl</A>
+
+
+<P><LI>
+<P>
+<A
+HREF="http://www.egroups.com/group/modperl/">http://www.egroups.com/group/modperl/</A>
+
+
+</UL>
</DL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
@@ -16311,6 +19216,12 @@
HREF="http://www.apache.org/docs/handler.html">http://www.apache.org/docs/handler.html</A>
+<P><LI><STRONG><A NAME="item_mod_rewrite">mod_rewrite Guide</A></STRONG>
+<P>
+<A
+HREF="http://www.engelschall.com/pw/apache/rewriteguide/">http://www.engelschall.com/pw/apache/rewriteguide/</A>
+
+
</UL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
@@ -16319,7 +19230,7 @@
<P><LI><STRONG><A NAME="item_Perl">Perl DBI examples</A></STRONG>
<P>
<A
-HREF="http://eskimo.tamu.edu/~jbaker/dbi-examples.html">http://eskimo.tamu.edu/~jbaker/dbi-examples.html</A>
+HREF="http://www.saturn5.com/~jwb/dbi-examples.html">http://www.saturn5.com/~jwb/dbi-examples.html</A>
(by Jeffrey William Baker).
<P><LI><STRONG><A NAME="item_DBI">DBI at Hermetica</A></STRONG>
@@ -16382,6 +19293,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="advocacy.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -16395,7 +19316,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/29/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
@@ -16473,6 +19394,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
@@ -16580,6 +19510,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="help.html">Prev</A> | <A HREF="index.html">Main Page</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.5 +19 -0 modperl-site/guide/browserbugs.html
Index: browserbugs.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/browserbugs.html,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- browserbugs.html 1999/08/17 19:03:34 1.4
+++ browserbugs.html 1999/09/25 23:13:52 1.5
@@ -43,6 +43,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Preventing_QUERY_STRING_from_get">Preventing QUERY_STRING from getting corrupted because of &entity key names.</A></H1></CENTER>
@@ -82,6 +91,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="debug.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="modules.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.18 +412 -10 modperl-site/guide/config.html
Index: config.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/config.html,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- config.html 1999/08/17 19:03:34 1.17
+++ config.html 1999/09/25 23:13:52 1.18
@@ -31,6 +31,14 @@
<LI><A HREF="#Alias_Configurations">Alias Configurations</A>
<LI><A HREF="#Location_Configuration">Location Configuration</A>
+ <LI><A HREF="#PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A>
+ <LI><A HREF="#Perl_Handlers">Perl*Handlers</A>
+ </UL>
+
+ <LI><A HREF="#STACKED_HANDLERS">STACKED HANDLERS</A>
+ <LI><A HREF="#PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A>
+ <UL>
+
<LI><A HREF="#PerlFreshRestart">PerlFreshRestart</A>
<LI><A HREF="#_perl_status_location">/perl-status location</A>
<UL>
@@ -65,12 +73,13 @@
<LI><A HREF="#My_script_works_under_cgi_bin_b">My script works under cgi-bin, but when called via mod_perl I see A 'Save-As' prompt</A>
<LI><A HREF="#Is_there_a_way_to_provide_a_diff">Is there a way to provide a different startup.pl file for each individual virtual host</A>
<LI><A HREF="#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A>
- <LI><A HREF="#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with</A>
+ <LI><A HREF="#A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A>
<LI><A HREF="#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
</UL>
<LI><A HREF="#Configuration_Security_Concerns">Configuration Security Concerns</A>
<LI><A HREF="#Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A>
+ <LI><A HREF="#Apache_restarts_twice_on_start">Apache restarts twice on start</A>
</UL>
<!-- INDEX END -->
@@ -86,6 +95,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="mod_perl_Specific_Configuration">mod_perl Specific Configuration</A></H1></CENTER>
@@ -196,8 +214,8 @@
invocation. You will want to turn this off for nph (non-parsed-headers)
scripts. <CODE>PerlSendHeader On</CODE> means to call
<CODE>ap_send_http_header()</CODE> after parsing your script headers. It is only meant for CGI emulation, its
-always better to use <CODE>CGI-</CODE>header> from
-<CODE>CGI.pm</CODE> module or <CODE>$r-&gt;send_http_header</CODE> directly.
+always better to use <CODE>CGI-&gt;header</CODE>
+from <CODE>CGI.pm</CODE> module or <CODE>$r-&gt;send_http_header</CODE> directly.
<P>
Remember the <STRONG>Alias</STRONG> from the section above? We must use the same
@@ -235,6 +253,350 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A></H2></CENTER>
+<P>
+You may load modules from the config file at server startup via:
+
+<P>
+<PRE> PerlModule Apache::DBI CGI DBD::Mysql
+</PRE>
+<P>
+There is a limit of 10 <CODE>PerlModule</CODE>'s, if you need more to be loaded when the server starts, use one <CODE>PerlModule</CODE> to pull in many or write them all in a regular perl syntax and put them
+into a startup file which can be loaded with use of the <CODE>PerlRequire</CODE> directive.
+
+<P>
+<PRE> PerlRequire /home/httpd/perl/lib/startup.pl
+</PRE>
+<P>
+Both <CODE>PerlModule</CODE> and <CODE>PerlRequire</CODE> are implemented by <CODE>require(),</CODE> but there is a subtle change. <CODE>PerlModule</CODE> works like <CODE>use(),</CODE> expecting a module name without <CODE>.pm</CODE> extension and slashes.
+<CODE>Apache::DBI</CODE> is OK, while <CODE>Apache/DBI.pm</CODE> is not. <CODE>PerlRequire</CODE> is the opposite to <CODE>PerlModule</CODE> -- it expects a relative or full path to the module or a filename, like in
+the example above.
+
+<P>
+As with any file that's being <CODE>required()</CODE> -- it must return a <STRONG>true</STRONG>
+value, to ensure that this happens don't forget to add <CODE>1;</CODE> at the end of such files.
+
+<P>
+We must stress that all the code that is run at the server initialization
+time is run with root priveleges if you are executing it as a root user
+(you have to unless you choose an unpriveledged port, above 1024.
+somethings that you might have to if you don't have a root access. Just
+remember that you better pick a well known port like 8000 or 8080 since
+other non-standard ports might be blocked by firewalls that protect many
+organizations and individuals). This means that anyone who has write access
+to a script or module that is loaded by <CODE>PerlModule</CODE> or <CODE>PerlRequire</CODE>, effectively has root access to the system. You might want to take a look
+at the new and experimental <CODE>PerlOpmask</CODE> directive and <CODE>PERL_OPMASK_DEFAULT</CODE>
+compile time option to try to disable some dangerous operators.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Perl_Handlers">Perl*Handlers</A></H2></CENTER>
+<P>
+As you know Apache specifies about 11 phases of the request loop, namely in
+that order: Post-Read-Request, URI Translation, Header Parsing, Access
+Control, Authentication, Authorization, MIME type checking, FixUp, Response
+(Content phase). Logging and finally Cleanup. These are the stages of a
+request where the Apache API allows a module to step in and do something.
+There is a dedicated PerlHandler for each of these stages. Namely:
+
+<P>
+<PRE> PerlChildInitHandler
+ PerlPostReadRequestHandler
+ PerlInitHandler
+ PerlTransHandler
+ PerlHeaderParserHandler
+ PerlAccessHandler
+ PerlAuthenHandler
+ PerlAuthzHandler
+ PerlTypeHandler
+ PerlFixupHandler
+ PerlHandler
+ PerlLogHandler
+ PerlCleanupHandler
+ PerlChildExitHandler
+</PRE>
+<P>
+The first 4 handlers cannot be used in the <CODE><Location</CODE>>,
+<CODE><Directory</CODE>>, <CODE><Files</CODE>> and <CODE>.htaccess</CODE> file, the main reason is all the above require a known path to the file in
+order to bind a requested path with one or more of the identifiers above.
+Starting from <CODE>PerlHeaderParserHandler</CODE> (5th) URI is allready being mapped to a physical pathname, thus can be used
+to match the <CODE><Location</CODE>>,
+<CODE><Directory</CODE>> or <CODE><Files</CODE>> configuration section, or to look at
+<CODE>.htaccess</CODE> file if exists at the specified directory in the translated path.
+
+<P>
+The Apache documentation (or even better -- the ``Writing Apache Modules
+with Perl and C'' book by Doug MacEachern and Lincoln Stein) will tell you
+all about those stages and what your modules can do. By default, these
+hooks are disabled at compile time, see the INSTALL document for
+information on enabling these hooks.
+
+<P>
+Note that by default Perl API expects a subrotine called <CODE>handler</CODE> to handle the request in the registered PerlHandler module. Thus if your
+module implements this subrotine, you can register the handler as simple as
+writing:
+
+<P>
+<PRE> Perl*Handler Apache::SomeModule
+</PRE>
+<P>
+replace <EM>Perl*Handler</EM> with a wanted name of the handler. mod_perl will preload the specified
+module for you. But if you decide to give the handler code a different
+name, like <CODE>my_handler</CODE>, you must preload the module and to write explicitly the chosen name.
+
+<P>
+<PRE> PerlModule Apache::SomeModule
+ Perl*Handler Apache::SomeModule::my_handler
+</PRE>
+<P>
+Please note that the former approach will not preload the module at the
+startup, so either explicitly preload it with <CODE>PerlModule</CODE>
+directive, add it to the startup file or use a nice shortcut the
+<CODE>Perl*Handler</CODE> syntax suggests:
+
+<P>
+<PRE> Perl*Handler +Apache::SomeModule
+</PRE>
+<P>
+Notice the leading <CODE>+</CODE> character. It's equal to:
+
+<P>
+<PRE> PerlModule Apache::SomeModule
+ Perl*Handler Apache::SomeModule
+</PRE>
+<P>
+If a module wishes to know what handler is currently being run, it can find
+out with the <EM>current_callback</EM> method. This method is most useful to <EM>PerlDispatchHandlers</EM> who wish to only take action for certain phases.
+
+<P>
+<PRE> if($r->current_callback eq "PerlLogHandler") {
+ $r->warn("Logging request");
+ }
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="STACKED_HANDLERS">STACKED HANDLERS</A></H1></CENTER>
+<P>
+With the mod_perl stacked handlers mechanism, it is possible for more than
+one <CODE>Perl*Handler</CODE> to be defined and run during each stage of a request.
+
+<P>
+Perl*Handler directives can define any number of subroutines, e.g. (in
+config files)
+
+<P>
+<PRE> PerlTransHandler OneTrans TwoTrans RedTrans BlueTrans
+</PRE>
+<P>
+With the method, <CODE>Apache-&gt;push_handlers()</CODE>, callbacks can be added to the stack by scripts at runtime by mod_perl
+scripts.
+
+<P>
+<CODE>Apache-&gt;push_handlers()</CODE> takes the callback hook name as its first argument and a subroutine name or
+reference as its second. e.g.:
+
+<P>
+<PRE> Apache->push_handlers("PerlLogHandler", \&first_one);
+
+ $r->push_handlers("PerlLogHandler", sub {
+ print STDERR "__ANON__ called\n";
+ return 0;
+ });
+</PRE>
+<P>
+After each request, this stack is cleared out.
+
+<P>
+All handlers will be called unless a handler returns a status other than <CODE>OK</CODE> or <CODE>DECLINED</CODE>.
+
+<P>
+example uses:
+
+<P>
+<CODE>CGI.pm</CODE> maintains a global object for its plain function interface. Since the
+object is global, it does not go out of scope, DESTROY is never called. <CODE>CGI-&gt;new</CODE> can call:
+
+<P>
+<PRE> Apache->push_handlers("PerlCleanupHandler", \&CGI::_reset_globals);
+</PRE>
+<P>
+This function will be called during the final stage of a request,
+refreshing <CODE>CGI.pm</CODE>'s globals before the next request comes in.
+
+<P>
+<CODE>Apache::DCELogin</CODE> establishes a DCE login context which must exist for the lifetime of a
+request, so the <CODE>DCE::Login</CODE> object is stored in a global variable. Without stacked handlers, users must
+set
+
+<P>
+<PRE> PerlCleanupHandler Apache::DCELogin::purge
+</PRE>
+<P>
+in the configuration files to destroy the context. This is not
+``user-friendly''. Now, <CODE>Apache::DCELogin::handler</CODE> can call:
+
+<P>
+<PRE> Apache->push_handlers("PerlCleanupHandler", \&purge);
+</PRE>
+<P>
+Persistent database connection modules such as <CODE>Apache::DBI</CODE> could push a <CODE>PerlCleanupHandler</CODE> handler that iterates over <CODE>%Connected</CODE>, refreshing connections or just checking that ones have not gone stale.
+Remember, by the time we get to <CODE>PerlCleanupHandler</CODE>, the client has what it wants and has gone away, we can spend as much time
+as we want here without slowing down response time to the client (but the
+process is unavailable for serving new request befor the operation is
+completed).
+
+<P>
+<CODE>PerlTransHandlers</CODE> may decide, based on URI or other condition, whether or not to handle a
+request, e.g. <CODE>Apache::MsqlProxy</CODE>. Without stacked handlers, users must configure:
+
+<P>
+<PRE> PerlTransHandler Apache::MsqlProxy::translate
+ PerlHandler Apache::MsqlProxy
+</PRE>
+<P>
+<CODE>PerlHandler</CODE> is never actually invoked unless <CODE>translate()</CODE> sees the request is a proxy request (<CODE>$r-&gt;proxyreq</CODE>), if it is a proxy request, <CODE>translate()</CODE> sets <CODE>$r-&gt;handler("perl-script")</CODE>, only then will <CODE>PerlHandler</CODE> handle the request. Now, users do not have to specify <CODE>PerlHandler Apache::MsqlProxy</CODE>, the <CODE>translate()</CODE>
+function can set it with <CODE>push_handlers()</CODE>.
+
+<P>
+Includes, footers, headers, etc., piecing together a document, imagine (no
+need for SSI parsing!):
+
+<P>
+<PRE> PerlHandler My::Header Some::Body A::Footer
+</PRE>
+<P>
+A little test:
+
+<P>
+<PRE> #My.pm
+ package My;
+</PRE>
+<P>
+<PRE> sub header {
+ my $r = shift;
+ $r->content_type("text/plain");
+ $r->send_http_header;
+ $r->print("header text\n");
+ }
+ sub body { shift->print("body text\n") }
+ sub footer { shift->print("footer text\n") }
+ 1;
+ __END__
+</PRE>
+<P>
+<PRE> #in config
+ <Location /foo>
+ SetHandler "perl-script"
+ PerlHandler My::header My::body My::footer
+ </Location>
+</PRE>
+<P>
+Parsing the output of another PerlHandler? this is a little more tricky,
+but consider:
+
+<P>
+<PRE> <Location /foo>
+ SetHandler "perl-script"
+ PerlHandler OutputParser SomeApp
+ </Location>
+
+ <Location /bar>
+ SetHandler "perl-script"
+ PerlHandler OutputParser AnotherApp
+ </Location>
+</PRE>
+<P>
+Now, OutputParser goes first, but it <CODE>untie()'s</CODE> <CODE>*STDOUT</CODE> and re-tie()'s to its own package like so:
+
+<P>
+<PRE> package OutputParser;
+</PRE>
+<P>
+<PRE> sub handler {
+ my $r = shift;
+ untie *STDOUT;
+ tie *STDOUT => 'OutputParser', $r;
+ }
+
+ sub TIEHANDLE {
+ my($class, $r) = @_;
+ bless { r => $r}, $class;
+ }
+
+ sub PRINT {
+ my $self = shift;
+ for (@_) {
+ #do whatever you want to $_
+ $self->{r}->print($_ . "[insert stuff]");
+ }
+ }
+</PRE>
+<P>
+<PRE> 1;
+ __END__
+</PRE>
+<P>
+To build in this feature, configure with:
+
+<P>
+<PRE> % perl Makefile.PL PERL_STACKED_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
+</PRE>
+<P>
+Another method <CODE>Apache-&gt;can_stack_handlers</CODE> will return TRUE if mod_perl was configured with <CODE>PERL_STACKED_HANDLERS=1</CODE>, FALSE otherwise.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A></H1></CENTER>
+<P>
+If a Perl*Handler is prototyped with <CODE>$$</CODE>, this handler will be invoked as method. e.g.
+
+<P>
+<PRE> package My;
+ @ISA = qw(BaseClass);
+
+ sub handler ($$) {
+ my($class, $r) = @_;
+ ...;
+ }
+
+ package BaseClass;
+
+ sub method ($$) {
+ my($class, $r) = @_;
+ ...;
+ }
+ __END__
+</PRE>
+<P>
+Configuration:
+
+<P>
+<PRE> PerlHandler My
+</PRE>
+<P>
+or
+
+<P>
+<PRE> PerlHandler My->handler
+</PRE>
+<P>
+Since the handler is invoked as a method, it may inherit from other
+classes:
+
+<P>
+<PRE> PerlHandler My->method
+</PRE>
+<P>
+In this case, the <CODE>My</CODE> class inherits this method from <CODE>BaseClass</CODE>.
+
+<P>
+To build in this feature, configure with:
+
+<P>
+<PRE> % perl Makefile.PL PERL_METHOD_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="PerlFreshRestart">PerlFreshRestart</A></H2></CENTER>
<P>
To reload <CODE>PerlRequire</CODE>, <CODE>PerlModule</CODE>, other <CODE>use()</CODE>'d modules and flush the <CODE>Apache::Registry</CODE> cache on server restart, add:
@@ -343,6 +705,9 @@
<EM>ENVironment</EM> variables to your scripts. you can access them in your scripts through <CODE>%ENV</CODE> (e.g. <CODE>$ENV{"key"}</CODE>).
<P>
+Regarding the setting of <CODE>PerlPassEnv PERL5LIB</CODE> in httpd.conf If you turn on taint checks (<CODE>PerlTaintMode On</CODE>), <CODE>$ENV{PERL5LIB}</CODE> will be ignored (unset).
+
+<P>
<CODE>PerlSetVar</CODE> is very similar to <CODE>PerlSetEnv</CODE>, but you extract it with another method. In <Perl> sections:
<P>
@@ -690,10 +1055,24 @@
<P>
You can watch how have you configured the <CODE><Perl</CODE>> sections through the <A HREF="././config.html#_perl_status_location">/perl-status</A> location, by choosing the <STRONG>Perl Sections</STRONG> from the menu.
+<P>
+You can dump the configuration by <CODE><Perl</CODE>> sections configuration this way:
+
+<P>
+<PRE> <Perl>
+ use Apache::PerlSections();
+ ...
+ print STDERR Apache->PerlSections->dump();
+ </Perl>
+</PRE>
+<P>
+Alternatively you can store it in a file:
+
+<P>
+<PRE> Apache::PerlSections->store("httpd_config.pl");
+</PRE>
<P>
-<A
-HREF="http://www.modperl.com/book/chapters/ch8.html#Debugging_B_E_lt_PerlE_gt_Sect">http://www.modperl.com/book/chapters/ch8.html#Debugging_B_E_lt_PerlE_gt_Sect</A>
-shows how can you dump the contents of your <CODE><Perl</CODE>> sections to the error_log.
+You can then <CODE>require()</CODE> that file in some other <CODE><Perl</CODE>> section.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
@@ -888,8 +1267,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with
-the same path from the second virtual host</A></H2></CENTER>
+<CENTER><H2><A NAME="A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A></H2></CENTER>
<P>
This has been a bug before, last fixed in 1.15_01, i.e. if you are running
1.15, that could be the problem. You should set this variable in a startup
@@ -903,7 +1281,8 @@
script running for more than one Virtual host on the same machine, this can
be a waste, right? Set it to 0 in a startup script if you want to turn it
off and have this bug as a feature. (Only makes sense if you are sure that
-there will be no <STRONG>other</STRONG>scripts named by the same path/name)
+there will be no <STRONG>other</STRONG>scripts named by the same path/name). It also saves you some memory on the
+way.
<P>
<PRE> $Apache::Registry::NameWithVirtualHost = 0;
@@ -972,7 +1351,20 @@
<P>
Note that you cannot have <CODE>Files</CODE> derective inside <CODE>Location</CODE>, but you can have <CODE>Files</CODE> inside <CODE>Directory</CODE>.
+<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Apache_restarts_twice_on_start">Apache restarts twice on start</A></H1></CENTER>
+<P>
+When the server is restarted. the configuration and module initialization
+phases are called again (twice in total). To ensure that the future restart
+will workout correctly, Apache actually runs these two phases twice during
+server startup, to check that all modules can survive a restart.
+
+<P>
+(META: And add an example that writes to the log file - I was restarted 1,
+2 times)
+
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
book can be purchased online from <a
@@ -982,6 +1374,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="install.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="frequent.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -995,7 +1397,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/15/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
1.18 +19 -0 modperl-site/guide/control.html
Index: control.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/control.html,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- control.html 1999/08/17 19:03:34 1.17
+++ control.html 1999/09/25 23:13:53 1.18
@@ -51,6 +51,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Restarting_techniques">Restarting techniques</A></H1></CENTER>
@@ -950,6 +959,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="frequent.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.7 +19 -0 modperl-site/guide/databases.html
Index: databases.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/databases.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- databases.html 1999/08/17 19:03:35 1.6
+++ databases.html 1999/09/25 23:13:53 1.7
@@ -70,6 +70,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Why_Relational_SQL_Databases">Why Relational (SQL) Databases</A></H1></CENTER>
@@ -1181,6 +1190,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="security.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="dbm.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.7 +24 -3 modperl-site/guide/dbm.html
Index: dbm.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/dbm.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- dbm.html 1999/08/17 19:03:35 1.6
+++ dbm.html 1999/09/25 23:13:54 1.7
@@ -46,6 +46,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Where_and_Why_to_use_dbm_files">Where and Why to use dbm files</A></H1></CENTER>
@@ -244,7 +253,7 @@
BEGIN {
# RCS/CVS complient: must be all one line, for MakeMaker
- $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.6 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
+ $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.7 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
}
@@ -394,7 +403,8 @@
A simple tie, READ lock and untie
<P>
-<PRE> my %mydb = ();
+<PRE> my $dbfile = "/tmp/test";
+ my %mydb = ();
my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
print $mydb{'stas'} if exists $mydb{'stas'};
# sync and untie
@@ -421,7 +431,8 @@
Perform both, read and write operations:
<P>
-<PRE> my %mydb = ();
+<PRE> my $dbfile = "/tmp/test";
+ my %mydb = ();
my $db = new DB_File::Wrap \%mydb, $dbfile;
print $mydb{'stas'} if exists $mydb{'stas'};
@@ -451,6 +462,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="databases.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="multiuser.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -464,7 +485,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/09/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
1.16 +69 -2 modperl-site/guide/debug.html
Index: debug.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/debug.html,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- debug.html 1999/08/17 19:03:35 1.15
+++ debug.html 1999/09/25 23:13:54 1.16
@@ -34,6 +34,8 @@
<LI><A HREF="#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
<LI><A HREF="#Monitoring_error_log_file">Monitoring error_log file</A>
<LI><A HREF="#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
+ <LI><A HREF="#Spinning_httpds">Spinning httpds</A>
+ <LI><A HREF="#PROFILING">PROFILING</A>
<LI><A HREF="#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
<LI><A HREF="#Devel_Peek">Devel::Peek</A>
</UL>
@@ -51,6 +53,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A></H1></CENTER>
@@ -216,7 +227,7 @@
<P>
Current perl implementation does not restore the original apache's C
handler when you use <CODE>local $SIG{FOO}</CODE> clause. While save/restore of
-<CODE>$SIG{ALRM}</CODE> was fixed in the mod_perl 1.19_01 (CVS version) other signals are not yet
+<CODE>$SIG{ALRM}</CODE> was fixed in the mod_perl 1.19_01 (CVS version), other signals are not yet
fixed. The real fix should probably be in Perl itself.
<P>
@@ -252,6 +263,9 @@
die $@ if $@;
</PRE>
<P>
+If a timeout happens and <CODE>SIGALRM</CODE> is thrown, the <CODE>alarm()</CODE> will be reset, otherwise <CODE>alarm 0</CODE> is reached and timer is being reset as well.
+
+<P>
Now you would write:
<P>
@@ -266,6 +280,49 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Spinning_httpds">Spinning httpds</A></H1></CENTER>
+<P>
+To see where an httpd is ``spinning'', try adding this to your script or a
+startup file:
+
+<P>
+<PRE> use Carp ();
+ $SIG{'USR1'} = sub {
+ Carp::confess("caught SIGUSR1!");
+ };
+</PRE>
+<P>
+Then issue the command line:
+
+<P>
+<PRE> kill -USR1 <spinning_httpd_pid>
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="PROFILING">PROFILING</A></H1></CENTER>
+<P>
+It is possible to profile code run under mod_perl with the
+<CODE>Devel::DProf</CODE> module available on CPAN. However, you must have apache version 1.3b3 or
+higher and the <CODE>PerlChildExitHandler</CODE>
+enabled. When the server is started, <CODE>Devel::DProf</CODE> installs an
+<CODE>END</CODE> block to write the <CODE>tmon.out</CODE> file, which will be run when the server is shutdown. Here's how to start
+and stop a server with the profiler enabled:
+
+<P>
+<PRE> % setenv PERL5OPT -d:DProf
+ % httpd -X -d `pwd` &
+ ... make some requests to the server here ...
+ % kill `cat logs/httpd.pid`
+ % unsetenv PERL5OPT
+ % dprofpp
+</PRE>
+<P>
+See also: <CODE>Apache::DProf</CODE>
+
+
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="examples_of_strace_or_truss_us">examples of strace (or truss) usage</A></H1></CENTER>
<P>
(META: below are some snippets of strace outputs from list's emails)
@@ -367,6 +424,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="status.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="browserbugs.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -380,7 +447,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/17/1999
+ <BR>Last Modified at 09/22/1999
</FONT>
</B>
</TD>
1.5 +19 -0 modperl-site/guide/download.html
Index: download.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/download.html,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- download.html 1999/08/17 19:03:36 1.4
+++ download.html 1999/09/25 23:13:55 1.5
@@ -52,6 +52,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
@@ -159,6 +168,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="help.html">Prev</A> | <A HREF="index.html">Main Page</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.8 +19 -0 modperl-site/guide/frequent.html
Index: frequent.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/frequent.html,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- frequent.html 1999/08/17 19:03:36 1.7
+++ frequent.html 1999/09/25 23:13:55 1.8
@@ -44,6 +44,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
@@ -79,6 +88,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="config.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.10 +1067 -793 modperl-site/guide/guide-src.tar.gz
<<Binary file>>
1.11 +1616 -1420modperl-site/guide/guide.tar.gz
<<Binary file>>
1.6 +19 -0 modperl-site/guide/hardware.html
Index: hardware.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/hardware.html,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- hardware.html 1999/08/17 19:03:41 1.5
+++ hardware.html 1999/09/25 23:14:01 1.6
@@ -66,6 +66,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Is_it_important_">Is it important?</A></H1></CENTER>
@@ -460,6 +469,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="snippets.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="advocacy.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.17 +69 -5 modperl-site/guide/help.html
Index: help.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/help.html,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- help.html 1999/08/17 19:03:41 1.16
+++ help.html 1999/09/25 23:14:01 1.17
@@ -49,6 +49,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="READ_ME_FIRST">READ ME FIRST</A></H1></CENTER>
@@ -81,8 +90,11 @@
However, you are welcome to submit corrections and suggestions directly to
me at <A
HREF="mailto:sbekman@iname.com?subject=mod_perl%20guide%20corrections.">sbekman@iname.com?subject=mod_perl%20guide%20corrections.</A>
- <STRONG>But PLEASE
-NO QUESTIONS, they will be immediately deleted.</STRONG>
+If you are going to <STRONG>submit heavy corrections of the text</STRONG> (I love those!), please help me by downloading the source pages in POD
+(from the main age under the index) and directly editing them. I will use
+Emacs Ediff to perform an easy merge of your changes. Thank you! <STRONG>But PLEASE NO
+PERSONAL QUESTIONS, I didn't invite those by writing a guide. They all
+will be immediately deleted.</STRONG>
@@ -171,11 +183,47 @@
HREF="http://forum.swarthmore.edu/epigone/modperl">http://forum.swarthmore.edu/epigone/modperl</A>
. We owe it to Ken Williams.
+<P>
+More archives available:
+
+<UL>
+<P><LI>
<P>
-Another arhive: <A
+<A
HREF="http://www.geocrawler.com/lists/3/web/182/0/">http://www.geocrawler.com/lists/3/web/182/0/</A>
+<P><LI>
+<P>
+<A
+HREF="http://www.bitmechanic.com/mail-archives/modperl/">http://www.bitmechanic.com/mail-archives/modperl/</A>
+
+
+<P><LI>
+<P>
+<A
+HREF="http://www.mail-archive.com/modperl%40apache.org/">http://www.mail-archive.com/modperl%40apache.org/</A>
+
+
+<P><LI>
+<P>
+<A
+HREF="http://www.davin.ottawa.on.ca/archive/modperl/">http://www.davin.ottawa.on.ca/archive/modperl/</A>
+
+
+<P><LI>
+<P>
+<A
+HREF="http://www.progressive-comp.com/Lists/?l=apache-modperl&r=1&w=2#apache-modperl">http://www.progressive-comp.com/Lists/?l=apache-modperl&r=1&w=2#apache-modperl</A>
+
+
+<P><LI>
+<P>
+<A
+HREF="http://www.egroups.com/group/modperl/">http://www.egroups.com/group/modperl/</A>
+
+
+</UL>
</DL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
@@ -267,6 +315,12 @@
HREF="http://www.apache.org/docs/handler.html">http://www.apache.org/docs/handler.html</A>
+<P><LI><STRONG><A NAME="item_mod_rewrite">mod_rewrite Guide</A></STRONG>
+<P>
+<A
+HREF="http://www.engelschall.com/pw/apache/rewriteguide/">http://www.engelschall.com/pw/apache/rewriteguide/</A>
+
+
</UL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
@@ -275,7 +329,7 @@
<P><LI><STRONG><A NAME="item_Perl">Perl DBI examples</A></STRONG>
<P>
<A
-HREF="http://eskimo.tamu.edu/~jbaker/dbi-examples.html">http://eskimo.tamu.edu/~jbaker/dbi-examples.html</A>
+HREF="http://www.saturn5.com/~jwb/dbi-examples.html">http://www.saturn5.com/~jwb/dbi-examples.html</A>
(by Jeffrey William Baker).
<P><LI><STRONG><A NAME="item_DBI">DBI at Hermetica</A></STRONG>
@@ -338,6 +392,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="advocacy.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -351,7 +415,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/29/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
1.20 +87 -41 modperl-site/guide/index.html
Index: index.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/index.html,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- index.html 1999/08/17 19:03:41 1.19
+++ index.html 1999/09/25 23:14:02 1.20
@@ -27,8 +27,8 @@
<CENTER><P><B>Deploying mod_perl technology to give a rocket speed
to your CGI/perl scripts.</B></P></CENTER>
-<CENTER><P><B>Version 1.15
- Aug, 17 1999</B></P></CENTER>
+<CENTER><P><B>Version 1.16
+ Sep, 26 1999</B></P></CENTER>
<P>
<HR WIDTH="100%"></P>
@@ -46,6 +46,15 @@
<UL>
<LI><A HREF="intro.html#What_is_mod_perl">What is mod_perl</A>
+ <UL>
+
+ <LI><A HREF="intro.html#mod_cgi">mod_cgi</A>
+ <LI><A HREF="intro.html#C_API">C API</A>
+ <LI><A HREF="intro.html#Perl_API">Perl API</A>
+ <LI><A HREF="intro.html#Apache_Registry">Apache::Registry</A>
+ <LI><A HREF="intro.html#Apache_PerlRun">Apache::PerlRun</A>
+ </UL>
+
<LI><A HREF="intro.html#What_will_you_learn">What will you learn</A>
<LI><A HREF="intro.html#References_and_Acknowledgments">References and Acknowledgments</A>
</UL>
@@ -62,48 +71,54 @@
<LI><A HREF="porting.html#Exposing_Apache_Registry_secret">Exposing Apache::Registry secrets</A>
<LI><A HREF="porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it Does Not</A>
<LI><A HREF="porting.html#What_s_different_about_modperl">What's different about modperl</A>
- <UL>
-
- <LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
- <LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
- <LI><A HREF="porting.html#More_package_name_related_issues">More package name related issues</A>
- <LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
- <LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
- <LI><A HREF="porting.html#Using_format_">Using format()</A>
- <LI><A HREF="porting.html#Using_exit_">Using exit()</A>
- <LI><A HREF="porting.html#Running_from_shell">Running from shell</A>
- <LI><A HREF="porting.html#I_O_is_different">I/O is different</A>
- <LI><A HREF="porting.html#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
- <LI><A HREF="porting.html#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
- <LI><A HREF="porting.html#BEGIN_blocks">BEGIN blocks </A>
- <LI><A HREF="porting.html#END_blocks">END blocks</A>
- <LI><A HREF="porting.html#Switches_w_T">Switches -w, -T</A>
- <LI><A HREF="porting.html#strict_pragma">strict pragma</A>
- <LI><A HREF="porting.html#Turning_warnings_ON">Turning warnings ON</A>
- <LI><A HREF="porting.html#diagnostics_pragma">diagnostics pragma</A>
- <LI><A HREF="porting.html#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
- <LI><A HREF="porting.html#Global_Variables">Global Variables</A>
- <LI><A HREF="porting.html#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
- <LI><A HREF="porting.html#Apache_and_syslog">Apache and syslog</A>
- <LI><A HREF="porting.html#Memory_leakage">Memory leakage</A>
- </UL>
-
+ <LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
+ <LI><A HREF="porting.html#Messing_with_INC">Messing with @INC</A>
<LI><A HREF="porting.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
<UL>
<LI><A HREF="porting.html#Restarting_the_server">Restarting the server</A>
- <LI><A HREF="porting.html#Using_Apache_StatINC">Using Apache::StatINC</A>
- <LI><A HREF="porting.html#Reloading_only_specific_files">Reloading only specific files</A>
+ <LI><A HREF="porting.html#Using_Apache_StatINC_for_Develo">Using Apache::StatINC for Development Process</A>
+ <LI><A HREF="porting.html#Configuration_Files_Writing_Mo">Configuration Files: Writing, Modifying and Reloading.</A>
+ <UL>
+
+ <LI><A HREF="porting.html#Writing_Configuration_Files">Writing Configuration Files</A>
+ <LI><A HREF="porting.html#Reloading_Configuration_Files">Reloading Configuration Files</A>
+ <LI><A HREF="porting.html#Dynamically_updating_configurati">Dynamically updating configuration files</A>
+ </UL>
+
<LI><A HREF="porting.html#Reloading_handlers">Reloading handlers</A>
</UL>
+ <LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
+ <LI><A HREF="porting.html#More_package_name_related_issues">More package name related issues</A>
+ <LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
+ <LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
+ <LI><A HREF="porting.html#Using_format_and_write_">Using format() and write()</A>
+ <LI><A HREF="porting.html#Using_exit_">Using exit()</A>
+ <LI><A HREF="porting.html#Running_from_shell">Running from shell</A>
+ <LI><A HREF="porting.html#I_O_is_different">I/O is different</A>
+ <LI><A HREF="porting.html#Special_Perl_Variables">Special Perl Variables</A>
+ <LI><A HREF="porting.html#Generating_correct_HTTP_Headers">Generating correct HTTP Headers</A>
+ <LI><A HREF="porting.html#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
+ <LI><A HREF="porting.html#BEGIN_blocks">BEGIN blocks </A>
+ <LI><A HREF="porting.html#END_blocks">END blocks</A>
+ <LI><A HREF="porting.html#Switches_w_T">Switches -w, -T</A>
+ <LI><A HREF="porting.html#strict_pragma">strict pragma</A>
+ <LI><A HREF="porting.html#Turning_warnings_ON">Turning warnings ON</A>
+ <LI><A HREF="porting.html#diagnostics_pragma">diagnostics pragma</A>
+ <LI><A HREF="porting.html#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
+ <LI><A HREF="porting.html#Global_Variables">Global Variables</A>
+ <LI><A HREF="porting.html#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
+ <LI><A HREF="porting.html#Apache_and_syslog">Apache and syslog</A>
+ <LI><A HREF="porting.html#Memory_leakage">Memory leakage</A>
<LI><A HREF="porting.html#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
<LI><A HREF="porting.html#The_Script_is_too_dirty_but_It_">The Script is too dirty, but It does the job and I can't afford rewriting it.</A>
<LI><A HREF="porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
+ <LI><A HREF="porting.html#Sharing_variables_between_proces">Sharing variables between processes</A>
<LI><A HREF="porting.html#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
<LI><A HREF="porting.html#Finding_the_line_number_the_erro">Finding the line number the error/warning has been triggered at</A>
- <LI><A HREF="porting.html#Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
- <LI><A HREF="porting.html#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A>
+ <LI><A HREF="porting.html#Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A>
+ <LI><A HREF="porting.html#Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A>
</UL>
<P><LI><A HREF="performance.html"><B><FONT SIZE=+1>Performance. Benchmarks.</FONT></B></A></LI><P>
<UL>
@@ -118,6 +133,8 @@
<LI><A HREF="performance.html#Preload_Registry_Scripts">Preload Registry Scripts</A>
<LI><A HREF="performance.html#Avoid_Importing_Functions">Avoid Importing Functions</A>
+ <LI><A HREF="performance.html#PerlSetupEnv_Off">PerlSetupEnv Off</A>
+ <LI><A HREF="performance.html#_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A>
<LI><A HREF="performance.html#Shared_Memory">Shared Memory</A>
<LI><A HREF="performance.html#Checking_script_modification_tim">Checking script modification times</A>
<LI><A HREF="performance.html#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
@@ -221,15 +238,18 @@
</UL>
<LI><A HREF="install.html#Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A>
+ <LI><A HREF="install.html#Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A>
<LI><A HREF="install.html#Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A>
<LI><A HREF="install.html#Server_Installation_problems">Server Installation problems</A>
<UL>
+ <LI><A HREF="install.html#_skipping_test_on_this_plat">......skipping test on this platform</A>
<LI><A HREF="install.html#make_test_fails">make test fails</A>
<LI><A HREF="install.html#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
<LI><A HREF="install.html#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
</UL>
+ <LI><A HREF="install.html#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
<LI><A HREF="install.html#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
</UL>
<P><LI><A HREF="config.html"><B><FONT SIZE=+1>Server Configuration</FONT></B></A></LI><P>
@@ -240,6 +260,14 @@
<LI><A HREF="config.html#Alias_Configurations">Alias Configurations</A>
<LI><A HREF="config.html#Location_Configuration">Location Configuration</A>
+ <LI><A HREF="config.html#PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A>
+ <LI><A HREF="config.html#Perl_Handlers">Perl*Handlers</A>
+ </UL>
+
+ <LI><A HREF="config.html#STACKED_HANDLERS">STACKED HANDLERS</A>
+ <LI><A HREF="config.html#PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A>
+ <UL>
+
<LI><A HREF="config.html#PerlFreshRestart">PerlFreshRestart</A>
<LI><A HREF="config.html#_perl_status_location">/perl-status location</A>
<UL>
@@ -274,12 +302,13 @@
<LI><A HREF="config.html#My_script_works_under_cgi_bin_b">My script works under cgi-bin, but when called via mod_perl I see A 'Save-As' prompt</A>
<LI><A HREF="config.html#Is_there_a_way_to_provide_a_diff">Is there a way to provide a different startup.pl file for each individual virtual host</A>
<LI><A HREF="config.html#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A>
- <LI><A HREF="config.html#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with</A>
+ <LI><A HREF="config.html#A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A>
<LI><A HREF="config.html#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
</UL>
<LI><A HREF="config.html#Configuration_Security_Concerns">Configuration Security Concerns</A>
<LI><A HREF="config.html#Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A>
+ <LI><A HREF="config.html#Apache_restarts_twice_on_start">Apache restarts twice on start</A>
</UL>
<P><LI><A HREF="frequent.html"><B><FONT SIZE=+1>Frequent mod_perl problems</FONT></B></A></LI><P>
<UL>
@@ -345,6 +374,7 @@
<LI><A HREF="warnings.html#RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A>
<LI><A HREF="warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
<LI><A HREF="warnings.html#server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A>
+ <LI><A HREF="warnings.html#syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near "line arguments:"</A>
</UL>
<P><LI><A HREF="security.html"><B><FONT SIZE=+1>Protecting Your Site</FONT></B></A></LI><P>
<UL>
@@ -359,7 +389,8 @@
<LI><A HREF="security.html#Authentication_code_snippets">Authentication code snippets</A>
<UL>
- <LI><A HREF="security.html#Forcing_reauthenticating">Forcing reauthenticating</A>
+ <LI><A HREF="security.html#Forcing_re_authentication">Forcing re-authentication</A>
+ <LI><A HREF="security.html#OK_AUTH_REQUIRED_and_FORBIDDEN_">OK, AUTH_REQUIRED.and FORBIDDEN in Authentication handlers</A>
</UL>
</UL>
@@ -434,6 +465,8 @@
<LI><A HREF="debug.html#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
<LI><A HREF="debug.html#Monitoring_error_log_file">Monitoring error_log file</A>
<LI><A HREF="debug.html#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
+ <LI><A HREF="debug.html#Spinning_httpds">Spinning httpds</A>
+ <LI><A HREF="debug.html#PROFILING">PROFILING</A>
<LI><A HREF="debug.html#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
<LI><A HREF="debug.html#Devel_Peek">Devel::Peek</A>
</UL>
@@ -473,8 +506,6 @@
<P><LI><A HREF="snippets.html"><B><FONT SIZE=+1>Code Snippets</FONT></B></A></LI><P>
<UL>
- <LI><A HREF="snippets.html#Sending_MIME_headers">Sending MIME headers</A>
- <LI><A HREF="snippets.html#How_to_avoid_printing_the_header">How to avoid printing the header more than once</A>
<LI><A HREF="snippets.html#More_on_relative_paths">More on relative paths</A>
<LI><A HREF="snippets.html#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server</A>
<LI><A HREF="snippets.html#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
@@ -582,16 +613,31 @@
<HR>
<P>
-Now you can search the indexed version of the guide at <A
-HREF="http://www.perlreference.com/mod_perl/guide">perlreference.com</A>.
-
<HR>
+
+<A NAME="SEARCH"></A>
+<CENTER>
+<TABLE BORDER=10 CELLSPACING=2 CELLPADDING=8 >
+<TR BGCOLOR="gray" ALIGN=CENTER VALIGN=TOP>
+<TD ALIGN=CENTER VALIGN=TOP>
+<FONT COLOR=WHITE>
+Search mod_perl FAQs along with this guide
+<BR> at www.perlreference.com
+<FORM action="http://perlreference.com/cgi-bin/mod_perl/search.pl" method="GET">
+<INPUT type="text" name="q" value="" SIZE=15>
+<INPUT TYPE="submit" VALUE="Search">
+</FORM>
+</FONT>
+</TD></TR>
+</TABLE>
+</CENTER>
+
<CENTER>
<TABLE BORDER=10 CELLSPACING=2 CELLPADDING=8 >
<TR BGCOLOR="gray" ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=TOP>
<FONT COLOR=WHITE>
-<A NAME="SEARCH">Search perl.apache.org along with this guide.</A>
+Search perl.apache.org along with this guide.
<FORM ACTION="http://search.apache.org/" METHOD="POST">
<INPUT TYPE="text" NAME="keyword" value="" SIZE=15>
<input type="hidden" name="what" value="perl">
@@ -621,7 +667,7 @@
<TR ALIGN=CENTER VALIGN=TOP>
<TD ALIGN=CENTER VALIGN=CENTER><B><FONT SIZE=-1>Written by <A
-HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 08/17/1999
+HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 09/26/1999
</FONT></B></TD>
<TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" BORDER=0 ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></A>
1.7 +151 -1 modperl-site/guide/install.html
Index: install.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/install.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- install.html 1999/08/17 19:03:42 1.6
+++ install.html 1999/09/25 23:14:03 1.7
@@ -45,15 +45,18 @@
</UL>
<LI><A HREF="#Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A>
+ <LI><A HREF="#Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A>
<LI><A HREF="#Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A>
<LI><A HREF="#Server_Installation_problems">Server Installation problems</A>
<UL>
+ <LI><A HREF="#_skipping_test_on_this_plat">......skipping test on this platform</A>
<LI><A HREF="#make_test_fails">make test fails</A>
<LI><A HREF="#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
<LI><A HREF="#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
</UL>
+ <LI><A HREF="#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
</UL>
<!-- INDEX END -->
@@ -70,6 +73,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Configuration_and_Installation">Configuration and Installation</A></H1></CENTER>
@@ -340,6 +352,25 @@
for more information on local perl installations.
<P>
+So you end up with something like:
+
+<P>
+<PRE> $ gunzip <apache_x.x.xx.tar.gz | tar xvf -
+ $ gunzip <mod_perl-x.xx.tar.gz | tar xvf -
+ $ cd mod_perl-x.xx
+ $ perl Makefile.PL \
+ APACHE_SRC=../apache-1.3.X/src \
+ DO_HTTPD=1 \
+ USE_APACI=1 \
+ EVERYTHING=1 \
+ APACI_ARGS=--sbindir=/home/stas/sbin/httpd_perl, \
+ --sysconfdir=/home/stas/etc/httpd_perl, \
+ --localstatedir=/home/stas/var/httpd_perl, \
+ --runtimedir=/home/stas/var/httpd_perl/run, \
+ --logfiledir=/home/stas/var/httpd_perl/logs, \
+ --proxycachedir=/home/stas/var/httpd_perl/proxy
+</PRE>
+<P>
You will not be able to have the server listen to a port lower then 1024 if
you are not starting it as <CODE>root</CODE>, so choose a port number above 1024. (I use 8080 in most cases). Note that
you will have to use a URL like <CODE>http://www.nowhere.com:8080</CODE> in that case, but that is not a problem since usually users do not directly
@@ -378,6 +409,17 @@
</UL>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A></H1></CENTER>
+<P>
+Sure, you can take a look at the symbols inside the httpd executable. e.g.
+if you want to see whether you have enabled PERL_AUTH=1 while building the
+mod_perl, you do:
+
+<P>
+<PRE> nm httpd | grep perl_authenticate
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A></H1></CENTER>
<P>
It is possible to determine which options were given to modperl's
@@ -412,6 +454,56 @@
<CENTER><H1><A NAME="Server_Installation_problems">Server Installation problems</A></H1></CENTER>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="_skipping_test_on_this_plat">......skipping test on this platform</A></H2></CENTER>
+<P>
+While doing <CODE>make test</CODE> you would notice that some of the tests are being reported as skipped. The
+real reason is that you are missing some optional modules for these test to
+be passed. For a hint you might want to peek at the content of each test
+(you will find them all in the <CODE>./t</CODE> directory (mnemonic - t, tests). I'll list a few examples, but of course
+the requirements might be changed in the future.
+
+<P>
+> modules/cookie......skipping test on this platform
+
+<P>
+install libapreq
+
+<P>
+> modules/psections...skipping test on this platform
+
+<P>
+install Devel::Symdump / Data::Dumper
+
+<P>
+> modules/request.....skipping test on this platform
+
+<P>
+libapreq
+
+<P>
+> modules/sandwich....skipping test on this platform
+
+<P>
+Apache::Sandwich
+
+<P>
+> modules/stage.......skipping test on this platform
+
+<P>
+Apache::Stage
+
+<P>
+> modules/symbol......skipping test on this platform
+
+<P>
+Devel::Symdump
+
+<P>
+Chances are that all of these are installed if you use <CODE>CPAN.pm</CODE> to
+<CODE>install Bundle::Apache</CODE>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="make_test_fails">make test fails</A></H2></CENTER>
<P>
There are two configuration parameters: <CODE>PREP_HTTPD</CODE> and <CODE>DO_HTTPD</CODE>, that you can use in:
@@ -472,6 +564,54 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="mod_auth_dbm_nuances">mod_auth_dbm nuances</A></H1></CENTER>
+<P>
+If you are a user of <STRONG>mod_auth_dbm</STRONG> or <STRONG>mod_auth_db</STRONG>, you may need to edit Perl's <CODE>Config</CODE> module. When Perl is configured it attempts to find libraries for ndbm,
+gdbm, db, etc., for the *DBM*_File modules. By default, these libraries are
+linked with Perl and remembered by the <STRONG>Config</STRONG> module. When mod_perl is configured with apache, the <STRONG>ExtUtils::Embed</STRONG> module returns these libraries to be linked with httpd so Perl extensions
+will work under mod_perl. However, the order in which these libraries are
+stored in
+<STRONG>Config.pm</STRONG>, may confuse <CODE>mod_auth_db*</CODE>. If <CODE>mod_auth_db*</CODE> does not work with mod_perl, take a look at this order with the following
+command:
+
+<P>
+<PRE> % perl -V:libs
+</PRE>
+<P>
+If <CODE>-lgdbm</CODE> or <CODE>-ldb</CODE> is before <CODE>-lndbm</CODE>, example:
+
+<P>
+<PRE> libs='-lnet -lnsl_s -lgdbm -lndbm -ldb -ldld -lm -lc -lndir -lcrypt';
+</PRE>
+<P>
+Edit <STRONG>Config.pm</STRONG> and move <CODE>-lgdbm</CODE> and <CODE>-ldb</CODE> to the end of the list. Here's how to find <STRONG>Config.pm</STRONG>:
+
+<P>
+<PRE> % perl -MConfig -e 'print "$Config{archlibexp}/Config.pm\n"'
+</PRE>
+<P>
+Another solution for building Apache/mod_perl+mod_auth_dbm under Solaris is
+to remove the DBM and NDBM ``emulation'' from libgdbm.a. Seems Solaris
+already provides its own DBM and NDBM, and there's no reason to build GDBM
+with them (for us anyway).
+
+<P>
+In our Makefile for GDBM, we changed
+
+<P>
+<PRE> OBJS = $(DBM_OF) $(NDBM_OF) $(GDBM_OF)
+</PRE>
+<P>
+to
+
+<P>
+<PRE> OBJS = $(GDBM_OF)
+</PRE>
+<P>
+Rebuild libgdbm, then Apache/mod_perl.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A></H1></CENTER>
<P>
Since most of the functionality that various apache mod_* modules provide
@@ -491,6 +631,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="scenario.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="config.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -504,7 +654,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/09/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
1.14 +148 -3 modperl-site/guide/intro.html
Index: intro.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/intro.html,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- intro.html 1999/08/17 19:03:42 1.13
+++ intro.html 1999/09/25 23:14:04 1.14
@@ -27,6 +27,15 @@
<UL>
<LI><A HREF="#What_is_mod_perl">What is mod_perl</A>
+ <UL>
+
+ <LI><A HREF="#mod_cgi">mod_cgi</A>
+ <LI><A HREF="#C_API">C API</A>
+ <LI><A HREF="#Perl_API">Perl API</A>
+ <LI><A HREF="#Apache_Registry">Apache::Registry</A>
+ <LI><A HREF="#Apache_PerlRun">Apache::PerlRun</A>
+ </UL>
+
<LI><A HREF="#What_will_you_learn">What will you learn</A>
<LI><A HREF="#References_and_Acknowledgments">References and Acknowledgments</A>
</UL>
@@ -44,6 +53,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="What_is_mod_perl">What is mod_perl</A></H1></CENTER>
@@ -91,6 +109,123 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="mod_cgi">mod_cgi</A></H2></CENTER>
+<P>
+When you run your CGI scripts by using a configuration of:
+
+<P>
+<PRE> ScriptAlias /cgi-bin/ /home/httpd/cgi-bin/
+</PRE>
+<P>
+you run it under a mod_cgi handler, you never define it explicitly. Apache
+does all the configuration work behind the scenes, when you use a
+ScriptAlias.
+
+<P>
+BTW, don't confuse it with a <CODE>ExecCGI</CODE> configuration option, it's being enabled so the script will be executed and
+not returned as a plain file. For example for mod_perl and <CODE>Apache::Registry</CODE> you would use a configuration like:
+
+<P>
+<PRE> <Location /perl>
+ SetHandler perl-script
+ PerlHandler Apache::Registry
+ Options ExecCGI
+ PerlSendHeader On
+ </Location>
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="C_API">C API</A></H2></CENTER>
+<P>
+META: complete
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Perl_API">Perl API</A></H2></CENTER>
+<P>
+META: complete
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Apache_Registry">Apache::Registry</A></H2></CENTER>
+<P>
+From the point of Perl API, <CODE>Apache::Registry</CODE> is just yet another handler that's not conceptually different from any
+other handler. It reads in the file, compiles, executes it and stores into
+the cache. Since the perl interpreter keeps running from child process'
+creation to its death, any code compiled by the interpreter is not removed
+from memory until the child dies.
+
+<P>
+To keep the script names from collisions, it prepends
+<CODE>Apache::ROOT::</CODE> and the mangled path of the URI to the key of the cached script. This key
+is actually a package name, the script resides in. So if you have requested
+a script <CODE>/perl/project/test.pl</CODE>, the scripts would be wrapped in code which starts with package
+declaration of:
+
+<P>
+<PRE> package Apache::ROOT::perl::project::test_e2pl;
+</PRE>
+<P>
+<CODE>Apache::Registry</CODE> also stores the script's last modification time. Everytime the script
+changes, the cached code would be discarded and recompiled using the
+modified source. However, it doesn't check any of the perl libraries the
+script might use.
+
+<P>
+<CODE>Apache::Registry</CODE> overrides the <CODE>CORE::exit()</CODE> with <Apache::exit()>, so the CGI scripts that used the
+<exit()> will run correctly. We will talk about all these details
+indepth later.
+
+<P>
+The last thing <CODE>Apache::Registry</CODE> does, is emulating of the mod_cgi's environment variables. Like <CODE>$ENV{SERVER_NAME}</CODE>, <CODE>$ENV{REMOTE_USER}</CODE>
+and so on. <STRONG>PerlSetupEnv Off</STRONG> disables this feature and saves some memory bits and CPU clocks.
+
+<P>
+From the point of mod_cgi (when you take the script that was running as a
+plain CGI under mod_cgi to run under mod_perl), there is almost no
+difference, but great speed improve, though much heavier memory usage
+(there is no free lunch :).
+
+<P>
+Just rememeber that the code is being cached, so it wouldn't cleanup the
+memory, like you used to with mod_cgi when the script was existing (it
+doesn't exit in mod_perl).
+
+<P>
+Also rememeber that any libraries that your script might
+<CODE>require()</CODE> or <CODE>use()</CODE> wouldn't be recompiled when
+changed.
+
+<P>
+Of course the book will answer all this issues in depth.
+
+<P>
+Just to show you what happens with your script, when it's being executed
+under <CODE>Apache::Registry</CODE>. If we take the simplest code of (URI <CODE>/perl/project/test.pl</CODE>)
+
+<P>
+<PRE> print "Content-type: text/html\n\n";
+ print "It works\n";
+</PRE>
+<P>
+<CODE>Apache::Registry</CODE> will convert it into the following:
+
+<P>
+<PRE> package Apache::ROOT::perl::project::test_e2pl;
+ use Apache qw(exit);
+ sub handler {
+ print "Content-type: text/html\n\n";
+ print "It works\n";
+ }
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Apache_PerlRun">Apache::PerlRun</A></H2></CENTER>
+<P>
+META: Complete
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="What_will_you_learn">What will you learn</A></H1></CENTER>
<P>
This document was written in an effort to help you start using Apache's
@@ -208,8 +343,8 @@
<P><LI>
<P>
-<STRONG>Eric Cholet</STRONG>, who wrote complete sections for the guide, and pointed out the errors in
-the guide.
+<STRONG>Eric Cholet</STRONG>, who wrote complete sections for the guide, and pointed out the errors the
+guide carried away.
<P><LI>
<P>
@@ -277,6 +412,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="index.html">Main Page</A> | <A HREF="start.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -290,7 +435,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/29/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
1.4 +858 -712 modperl-site/guide/mod_perl_guide.ps.gz
<<Binary file>>
1.8 +19 -0 modperl-site/guide/modules.html
Index: modules.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/modules.html,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- modules.html 1999/08/17 19:03:43 1.7
+++ modules.html 1999/09/25 23:14:07 1.8
@@ -49,6 +49,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Apache_Session_Maintain_sessi">Apache::Session - Maintain session state across HTTP requests</A></H1></CENTER>
@@ -312,6 +321,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="browserbugs.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="perl.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.8 +29 -2 modperl-site/guide/multiuser.html
Index: multiuser.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/multiuser.html,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- multiuser.html 1999/08/17 19:03:43 1.7
+++ multiuser.html 1999/09/25 23:14:07 1.8
@@ -43,6 +43,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="ISPs_providing_mod_perl_services">ISPs providing mod_perl services - a fantasy or reality.</A></H1></CENTER>
@@ -79,6 +88,14 @@
user (guest books, counters and etc - the same standard scripts ISPs
providing since they were born). So you have to say <STRONG>NO</STRONG> for this choice.
+<P>
+More things to think about are file permissions (any user who is allowed to
+write and run CGI script, can at least read if not write any other files
+that has a permissions of the web server. This has nothing to do with
+mod_perl, and there are solutions for that
+<CODE>suEXEC</CODE> and <CODE>cgiwrap</CODE> for example) and <CODE>Apache::DBI</CODE> connections (You can pick a connection from the pool of cached
+connenctions, opened by someone else by hacking the <CODE>Apache::DBI</CODE> code).
+
<P><LI>
<P>
But, hey why I cannot let my user to run his own server, so I clean my
@@ -207,7 +224,7 @@
<P>
-<A HREF="././config.html#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with the same path from the second virtual host</A>
+<A HREF="././config.html#A_Script_from_one_virtual_host_c">Sometimes the script from one virtual host calls a script with the same path from the second virtual host</A>
@@ -221,6 +238,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="dbm.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="status.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -234,7 +261,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/09/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
1.17 +31 -1 modperl-site/guide/obvious.html
Index: obvious.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/obvious.html,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- obvious.html 1999/08/17 19:03:44 1.16
+++ obvious.html 1999/09/25 23:14:08 1.17
@@ -58,6 +58,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
@@ -414,6 +423,17 @@
<P>
Also note that since the server is running in single mode, if the output
+returns HTML with <CODE><IMG</CODE>> tags, then the load of these will take a lot of time.
+
+<P>
+When you use Netscape client while your server is running in single-process
+mode, if the output returns a HTML with <CODE><IMG</CODE>> tags, then the load of these will take a lot of time, since the <CODE>KeepAlive</CODE>
+feature gets in the way. Netscape tries to open multiple connections and
+keep them open. Because there is only one server process listening, each
+connection has to time-out before the next succeeds. Turn off <CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect.
+
+<P>
+Also note that since the server is running in single mode, if the output
returns HTML with <CODE><IMG</CODE>> tags, then the load of these will take a lot of time. If you use
Netscape while your server is running in single-process mode, HTTP's <CODE>KeepAlive</CODE> feature gets in the way. Netscape tries to open multiple connections and
keep them open. Because there is only one server process listening, each
@@ -692,6 +712,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="control.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -705,7 +735,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/07/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
1.19 +111 -3 modperl-site/guide/performance.html
Index: performance.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/performance.html,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- performance.html 1999/08/17 19:03:44 1.18
+++ performance.html 1999/09/25 23:14:09 1.19
@@ -36,6 +36,8 @@
<LI><A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>
<LI><A HREF="#Avoid_Importing_Functions">Avoid Importing Functions</A>
+ <LI><A HREF="#PerlSetupEnv_Off">PerlSetupEnv Off</A>
+ <LI><A HREF="#_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A>
<LI><A HREF="#Shared_Memory">Shared Memory</A>
<LI><A HREF="#Checking_script_modification_tim">Checking script modification times</A>
<LI><A HREF="#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
@@ -83,6 +85,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Performance_The_Overall_picture">Performance: The Overall picture</A></H1></CENTER>
@@ -214,6 +225,21 @@
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H2><A NAME="Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A></H2></CENTER>
<P>
+(META: while the numbers and conclusions are mostly correct, need to
+rewrite the whole benchmark section using the GTop library to report the
+shared memory which is very important and will improve the benchmarks)
+
+<P>
+(META: Add the memory size tests when the server was compiled with
+EVERYTHING=1 and without it, does loading everything imposes a big change
+in the memory footprint? Probably the suggestion would be as follows: For a
+development server use EVERYTHING=1, while for a production if your server
+is pretty busy and/or low on memory and every bit is on account, only the
+required parts should be built in. BTW, remember that apache comes with
+many modules that are being built by default, and you might not need
+those!)
+
+<P>
I have conducted a few tests to benchmark the memory usage when some
modules are preloaded. The first set of tests checks the memory use with
Library Perl Module preload (only <CODE>CGI.pm</CODE>). The second set checks the compile method of <CODE>CGI.pm</CODE>. The third test checks the benefit of Library Perl Module preload but a
@@ -423,8 +449,24 @@
root 26792 0.0 0.0 3124 1440 - A 17:19:21 0:00 httpd
httpd 91052 0.0 1.0 6568 5040 - A 17:19:21 0:00 httpd
</PRE>
+<P>
+Observation: child httpd has grown by 3276K. Ouch: 512K more!!!
+
+<P>
+The reason is that when you preload at the startup all of the methods, they
+all are being precompiled, there are many of them and they take a big chunk
+of memory. If you don't use the <CODE>compile()</CODE> method, only the
+functions that are being used will be compiled. Yes, it will slightly slow
+down the first reposnse of each process, but the actuall memory usage will
+be lower. BTW, if you write in the script:
+
+<P>
+<PRE> use CGI qw(all);
+</PRE>
<P>
-Observation: child httpd has grown by 3276K. Great difference: 512K less!!!
+Only the symbols of all functions are being imported. While they are taking
+some space, it's smaller than the space that a compiled code of these
+functions might occupy.
<P>
<STRONG>Server restarted</STRONG>
@@ -534,6 +576,52 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="PerlSetupEnv_Off">PerlSetupEnv Off</A></H1></CENTER>
+<P>
+<CODE>PerlSetupEnv Off</CODE> is another optimization you might consider.
+
+<P>
+<EM>mod_perl</EM> fiddles with the environment to make it appear as if the script were being
+called under the CGI protocol. For example, the
+<CODE>$ENV{QUERY_STRING}</CODE> environment variable is initialized with the contents of <EM>Apache::args()</EM>, and <CODE>$ENV{SERVER_NAME}</CODE> is filled in from the value returned by <EM>Apache::server_hostname()</EM>.
+
+<P>
+But <CODE>%ENV</CODE> population is expensive. Those who have moved to the Perl Apache API no
+longer need this extra <CODE>%ENV</CODE> population, can gain by turning it <STRONG>Off</STRONG>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A></H1></CENTER>
+<P>
+Newer Perl versions also have build time options to reduce runtime memory
+consumption. These options might shrink down the size of your httpd by
+about ~150k (quite big number if you remember to multiply it by the number
+of chidren you use.)
+
+<P>
+<CODE>-DTWO_POT_OPTIMIZE</CODE> macro improves allocations of data with size close to a power of two; but
+this works for big allocations (starting with 16K by default). Such
+allocations are typical for big hashes and special-purpose scripts,
+especially image processing.
+
+<P>
+Perl memory allocation is by bucket with sizes close to powers of two.
+Because of these malloc overhead may be big, especially for data of size
+exactly a power of two. If <CODE>PACK_MALLOC</CODE> is defined, perl uses a slightly different algorithm for small allocations
+(up to 64 bytes long), which makes it possible to have overhead down to 1
+byte for allocations which are powers of two (and appear quite often).
+
+<P>
+Expected memory savings (with 8-byte alignment in <CODE>alignbytes</CODE>) is about 20% for typical Perl usage. Expected slowdown due to additional
+malloc overhead is in fractions of a percent (hard to measure, because of
+the effect of saved memory on speed).
+
+<P>
+You will find these and other memory improvement details in
+<CODE>perl5004delta.pod</CODE>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Shared_Memory">Shared Memory</A></H1></CENTER>
<P>
You've probably noticed that the word shared is being repeated many times
@@ -634,6 +722,10 @@
<CODE>Apache::Status</CODE> now includes a new StatusLexInfo option.
<P>
+Apache::Leak works better if you've built a libperld.a (see SUPPORT) and
+given PERL_DEBUG=1 to mod_perl's Makefile.PL
+
+<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Limiting_the_size_of_the_process">Limiting the size of the processes</A></H1></CENTER>
<P>
@@ -1756,7 +1848,8 @@
<PRE> PerlModule Apache::DBI
</PRE>
<P>
-It is important, to load this module before any other <CODE>ApacheDBI*</CODE> module!
+It is important, to load this module before any other <CODE>DBI</CODE>,
+<CODE>DBD::*</CODE> and <CODE>ApacheDBI*</CODE> modules!
<P>
<PRE> db.pl
@@ -1794,6 +1887,11 @@
that child process. See the <CODE>Apache::DBI</CODE> manpage to see the requirements for this method.
<P>
+You can also benefit from persistent connections by replacing
+<CODE>prepare()</CODE> with <CODE>prepare_cached().</CODE> But it can
+produce a little overhead (META, why?).
+
+<P>
Another problem is with timeouts: some databases disconnect the client
after a certain time of inactivity. This problem is known as <STRONG>morning
bug</STRONG>. The <CODE>ping()</CODE> method ensures that this will not happen. Some
@@ -1994,6 +2092,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="porting.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -2007,7 +2115,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/16/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
1.8 +19 -0 modperl-site/guide/perl.html
Index: perl.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/perl.html,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- perl.html 1999/08/17 19:03:44 1.7
+++ perl.html 1999/09/25 23:14:12 1.8
@@ -52,6 +52,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
@@ -340,6 +349,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="modules.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="snippets.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.20 +1915 -389 modperl-site/guide/porting.html
Index: porting.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/porting.html,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- porting.html 1999/08/17 19:03:44 1.19
+++ porting.html 1999/09/25 23:14:13 1.20
@@ -31,48 +31,54 @@
<LI><A HREF="#Exposing_Apache_Registry_secret">Exposing Apache::Registry secrets</A>
<LI><A HREF="#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it Does Not</A>
<LI><A HREF="#What_s_different_about_modperl">What's different about modperl</A>
- <UL>
-
- <LI><A HREF="#Script_s_name_space">Script's name space</A>
- <LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
- <LI><A HREF="#More_package_name_related_issues">More package name related issues</A>
- <LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
- <LI><A HREF="#Output_from_system_calls">Output from system calls</A>
- <LI><A HREF="#Using_format_">Using format()</A>
- <LI><A HREF="#Using_exit_">Using exit()</A>
- <LI><A HREF="#Running_from_shell">Running from shell</A>
- <LI><A HREF="#I_O_is_different">I/O is different</A>
- <LI><A HREF="#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
- <LI><A HREF="#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
- <LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
- <LI><A HREF="#END_blocks">END blocks</A>
- <LI><A HREF="#Switches_w_T">Switches -w, -T</A>
- <LI><A HREF="#strict_pragma">strict pragma</A>
- <LI><A HREF="#Turning_warnings_ON">Turning warnings ON</A>
- <LI><A HREF="#diagnostics_pragma">diagnostics pragma</A>
- <LI><A HREF="#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
- <LI><A HREF="#Global_Variables">Global Variables</A>
- <LI><A HREF="#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
- <LI><A HREF="#Apache_and_syslog">Apache and syslog</A>
- <LI><A HREF="#Memory_leakage">Memory leakage</A>
- </UL>
-
+ <LI><A HREF="#Script_s_name_space">Script's name space</A>
+ <LI><A HREF="#Messing_with_INC">Messing with @INC</A>
<LI><A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
<UL>
<LI><A HREF="#Restarting_the_server">Restarting the server</A>
- <LI><A HREF="#Using_Apache_StatINC">Using Apache::StatINC</A>
- <LI><A HREF="#Reloading_only_specific_files">Reloading only specific files</A>
+ <LI><A HREF="#Using_Apache_StatINC_for_Develo">Using Apache::StatINC for Development Process</A>
+ <LI><A HREF="#Configuration_Files_Writing_Mo">Configuration Files: Writing, Modifying and Reloading.</A>
+ <UL>
+
+ <LI><A HREF="#Writing_Configuration_Files">Writing Configuration Files</A>
+ <LI><A HREF="#Reloading_Configuration_Files">Reloading Configuration Files</A>
+ <LI><A HREF="#Dynamically_updating_configurati">Dynamically updating configuration files</A>
+ </UL>
+
<LI><A HREF="#Reloading_handlers">Reloading handlers</A>
</UL>
+ <LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
+ <LI><A HREF="#More_package_name_related_issues">More package name related issues</A>
+ <LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
+ <LI><A HREF="#Output_from_system_calls">Output from system calls</A>
+ <LI><A HREF="#Using_format_and_write_">Using format() and write()</A>
+ <LI><A HREF="#Using_exit_">Using exit()</A>
+ <LI><A HREF="#Running_from_shell">Running from shell</A>
+ <LI><A HREF="#I_O_is_different">I/O is different</A>
+ <LI><A HREF="#Special_Perl_Variables">Special Perl Variables</A>
+ <LI><A HREF="#Generating_correct_HTTP_Headers">Generating correct HTTP Headers</A>
+ <LI><A HREF="#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
+ <LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
+ <LI><A HREF="#END_blocks">END blocks</A>
+ <LI><A HREF="#Switches_w_T">Switches -w, -T</A>
+ <LI><A HREF="#strict_pragma">strict pragma</A>
+ <LI><A HREF="#Turning_warnings_ON">Turning warnings ON</A>
+ <LI><A HREF="#diagnostics_pragma">diagnostics pragma</A>
+ <LI><A HREF="#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
+ <LI><A HREF="#Global_Variables">Global Variables</A>
+ <LI><A HREF="#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
+ <LI><A HREF="#Apache_and_syslog">Apache and syslog</A>
+ <LI><A HREF="#Memory_leakage">Memory leakage</A>
<LI><A HREF="#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
<LI><A HREF="#The_Script_is_too_dirty_but_It_">The Script is too dirty, but It does the job and I can't afford rewriting it.</A>
<LI><A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
+ <LI><A HREF="#Sharing_variables_between_proces">Sharing variables between processes</A>
<LI><A HREF="#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
<LI><A HREF="#Finding_the_line_number_the_erro">Finding the line number the error/warning has been triggered at</A>
- <LI><A HREF="#Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
- <LI><A HREF="#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A>
+ <LI><A HREF="#Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A>
+ <LI><A HREF="#Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A>
</UL>
<!-- INDEX END -->
@@ -88,6 +94,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Document_Coverage">Document Coverage</A></H1></CENTER>
@@ -130,10 +145,16 @@
maintaining Perl modules. <A
HREF="http://world.std.com/~swmcd/steven/perl/module_mechanics.html">http://world.std.com/~swmcd/steven/perl/module_mechanics.html</A>
+
+<P>
+The information is very relevant to a mod_perl developer.
+
+<P><LI><STRONG><A NAME="item_The">The Eagle Book</A></STRONG>
+<P>
+``Writing Apache Modules with Perl and C'' is a ``must have'' book!
-<P><LI><STRONG><A NAME="item_Mod">Mod Perl Book</A></STRONG>
<P>
-A must have book! See the details at <A
+See the details at <A
HREF="http://www.modperl.com">http://www.modperl.com</A> .
</UL>
@@ -309,8 +330,8 @@
the <CODE>handler</CODE> subroutine.
<P>
-The workaround is to use global declared variables, with <CODE>vars</CODE>
-pragma.
+One of the workarounds is to use global declared variables, with
+<CODE>vars</CODE> pragma.
<P>
<PRE> # !/usr/bin/perl -w
@@ -355,16 +376,133 @@
print "Counter is equal to $main::counter !<BR>\n";
}
</PRE>
+<P>
+Another working but not quite good solution, is always to pass the variable
+as an argument. It's not good when the variable can be quite big, so it
+adds an overhead of time and memory.
+
+<P>
+<PRE> #!/usr/bin/perl -w
+ use strict;
+
+ print "Content-type: text/html\r\n\r\n";
+
+ my $counter = 0;
+
+ for (1..5) {
+ increment_counter($counter);
+ }
+
+ sub increment_counter{
+ my $counter = shift || 0 ;
+ $counter++;
+ print "Counter is equal to $counter !<BR>\n";
+ }
+</PRE>
+<P>
+It's important to understand that the closure effect happens only with code
+that <CODE>Apache::Registry</CODE> wraps with a declaration of the
+<CODE>handler</CODE> subroutine. If you put your code into a library or module, which the main
+script <CODE>require()'s</CODE> or <CODE>use()'s,</CODE> there is no such a
+problem. For example if we put the subroutine <CODE>increment_counter()</CODE>
+into a <CODE>mylib.pl</CODE> (e.g. save it in the same directory as the main script) and
+<CODE>require()</CODE> it, there will be no problem at all. (Don't forget
+the <CODE>1;</CODE> at the end of the library or the <CODE>require()</CODE> might fail.)
+
+<P>
+<PRE> mylib.pl:
+ ----------
+ sub increment_counter{
+ $counter++;
+ print "Counter is equal to $counter !<BR>\n";
+ }
+ 1;
+ ----------
+</PRE>
+<P>
+<PRE> counter.pl:
+ ----------
+ #!/usr/bin/perl -w
+ use strict;
+ require "./mylib.pl";
+
+ print "Content-type: text/html\r\n\r\n";
+
+ my $counter = 0;
+
+ for (1..5) {
+ increment_counter();
+ }
+
+ ----------
+</PRE>
+<P>
+Personally, unless the script is too short, I've got used to write all the
+code in the external libraries, and to have only a few lines in the main
+script, generally to call the main function of my library. Usually i call
+it <CODE>init()</CODE>. I don't worry about closure effect anymore (unless I create it myself :).
+
+<P>
+You shouldn't be intimidated by this issue at all, since Perl is your
+friend. Just keep the warnings mode On and whenever you will have this
+effect in place, Perl will gladly tell you that by saying:
+
+<P>
+<PRE> Variable "$counter" will not stay shared at ...[snipped]
+</PRE>
+<P>
+Just don't forget to check your error_log file, before going in production!
+
+<P>
+BTW, the above example was pretty boring. In my first days of using
+mod_perl, I wrote some cool user registration program. I'll show a very
+simple represenataion of this program.
+
+<P>
+<PRE> use CGI;
+ $q = new CGI;
+ my $name = $q->param('name')
+ print_respond();
+
+ sub print_respond{
+ print "Content-type: text/html\n\n";
+ print "Thank you, $name!";
+ }
+</PRE>
+<P>
+My boss and I have checked the program at the development server at it
+worked OK. So we decided to put it in production, everything was OK, but my
+boss decided to keep on checking by submitting a variations of his profile.
+Imagine what was the surprise when after submitting his name (let's say
+``Me Boss'' :), he saw a response ``Thank you, Stas Bekman!''. What
+happened is that I tried the production system as well. I was new to
+mod_perl stuff and was so excited with the speed improve, I didn't notice
+the clusure problem and it hit me. At the beginning I thought that may be
+Apache started to confuse connection, by returning responses from other
+people's requests. I was wrong of course. Why didn't we notice this when we
+were trying the system at our development server? Keep reading and you will
+understand what was the problem.
+
+<P>
+Now let's return to our original example and proceed with the second
+mystery we have noticed. Why did we see inconsistent results over numerous
+reloads. That's very simple. Every time a server gets a request to process,
+it handles it over one of the children, generally in a round robin fashion.
+So if you have 10 httpd children alive, first 10 reloads might seem to be
+correct. Since the closure starts to effect from the second re-invocation,
+consequent reloads return unexpected results. Moreover children don't serve
+the same request always consequently, at any given moment one of the
+children could serve more times the same script than any other. That's why
+we saw that strange behavior.
+
<P>
-Now let's proceed to the second mystery. Why did we see inconsistent
-results over numerous reloads. That's very simple. Every time a server gets
-a request to process, it handles it over one of the children, generally in
-a round robin fashion. So if you have 10 httpd children alive, first 10
-reloads might seem to be correct. Since the closure starts to effect from
-the second re-invocation, consequent reloads return unexpected results.
-Moreover children don't serve the same request always consequently, at any
-given moment one of the children could serve more times the same script
-than any other. That's why we saw that strange behavior.
+And now you understand why we didn't notice the problem with the user
+registration system in the last example I've presented. First we didn't
+look at the error_log files. (As a matter of fact we did, but there were so
+many warnings in there, we couldn't tell what are the important ones and
+what aren't). Then we didn't test the system under
+<CODE>-X</CODE> flag (single mode) and we have had too many server children running to
+notice the problem.
<P>
A workaround is to run the server in a single server mode. You achieve this
@@ -403,6 +541,138 @@
sometimes it helps.
<P>
+Sometimes it's very hard to understand what the warning complains about,
+you see the source code, but you cannot understand why some specific
+snippet produces warning. The mystery is in fact that the code can be
+called from different places, e.g when it's a subrotine.
+
+<P>
+I'll show you an example of such code.
+
+<P>
+<PRE> local $^W=1;
+ good();
+ bad();
+
+ sub good{
+ print_value("Perl");
+ }
+
+ sub bad{
+ print_value();
+ }
+
+ sub print_value{
+ my $var = shift;
+ print "My value is $var\n";
+ }
+</PRE>
+<P>
+In the code above, there is a sub that prints the passed value, sub
+<CODE>good</CODE> that passes correctly the value and sub <CODE>bad</CODE> where we forgot to pass it. When we run the script, we get the warning:
+
+<P>
+<PRE> Use of uninitialized value at ./warning.pl line 15.
+</PRE>
+<P>
+We can clearly see that there is an undefined value at the line, that
+attempts to print it:
+
+<P>
+<PRE> print "My value is $var\n";
+</PRE>
+<P>
+But how do we know, why it was undefined? The solution is quite simple.
+What we need is a full stack trace which triggered the warning.
+
+<P>
+The <CODE>Carp</CODE> module comes to help with its <CODE>cluck()</CODE> function. Let's modify the script:
+
+<P>
+<PRE> use Carp ();
+ local $SIG{__WARN__} = \&Carp::cluck;
+
+ local $^W=1;
+ good();
+ bad();
+
+ sub good{
+ print_value("Perl");
+ }
+
+ sub bad{
+ print_value();
+ }
+
+ sub print_value{
+ my $var = shift;
+ print "My value is $var\n";
+ }
+</PRE>
+<P>
+Now when we execute it, we would see:
+
+<P>
+<PRE> Use of uninitialized value at /home/httpd/perl/book/warning.pl line 17.
+ Apache::ROOT::perl::book::warning_2epl::print_value()
+ called at /home/httpd/perl/book/warning.pl line 12
+ Apache::ROOT::perl::book::warning_2epl::bad()
+ called at /home/httpd/perl/book/warning.pl line 5
+ Apache::ROOT::perl::book::warning_2epl::handler('Apache=SCALAR(0x84b1154)')
+ called at /usr/lib/perl5/site_perl/5.005/i386-linux/Apache/Registry.pm line 139
+ eval {...} called at
+ /usr/lib/perl5/site_perl/5.005/i386-linux/Apache/Registry.pm line 139
+ Apache::Registry::handler('Apache=SCALAR(0x84b1154)')
+ called at PerlHandler subroutine `Apache::Registry::handler' line 0
+ eval {...} called at PerlHandler subroutine `Apache::Registry::handler' line 0
+</PRE>
+<P>
+Take a moment to understand the trace, the only part that we are intersted
+in is the one that starts when actuall script is being called, so we can
+skip the <CODE>Apache::Registry</CODE> trace part. So we get:
+
+<P>
+<PRE> Use of uninitialized value at /home/httpd/perl/book/warning.pl line 17.
+ Apache::ROOT::perl::book::warning_2epl::print_value()
+ called at /home/httpd/perl/book/warning.pl line 12
+ Apache::ROOT::perl::book::warning_2epl::bad()
+ called at /home/httpd/perl/book/warning.pl line 5
+</PRE>
+<P>
+which tells us that the code that triggered the warning was:
+
+<P>
+<PRE> Apache::Registry code => bad() => print_value()
+</PRE>
+<P>
+We go into a <CODE>bad()</CODE> and indeed see that we forgot to pass the variable. Of course when you
+write a subroutine like <CODE>print_value</CODE> it could be a good idea to check the passed arguments before starting the
+execution. But it was ``good'' enough to show you how to ease the code
+debugging process.
+
+<P>
+Sure, you would say. I could find the problem by a simple inspectation of
+the code. You are right, but I promise you that your task would be quite
+complicated and time consuming for the code of thousands lines.
+
+<P>
+Notice the <CODE>local()</CODE> keyword, before the settings of the
+<CODE>$SIG{__WARN__}</CODE>. Since it's a global variable, forgetting to use
+<CODE>local()</CODE> will enforce this setting for all the scripts running under the same
+process. And if it's wanted behaviour, for example in the development
+server, you better do it in the startup file, where you can easily switch
+this feature on and off when the server restarts.
+
+<P>
+As you have noticed warnings report the line number the event happened at,
+so it's supposed to help to find the problematic code. The problem is that
+many times the line numbers are incorrect, because certain use of the <EM>eval</EM> operator and ``here'' documents are known to throw off Perl's line
+numbering.
+
+<P>
+META: move here the code that explains the settings of #line
+
+<P>
While having a warning mode turned <STRONG>On</STRONG> is a must in a development server, you better turn it globally <STRONG>Off</STRONG> in a production server, since if every CGI script generates only one
warning per request, and your server serves millions of requests per day -
your log file will eat up all of your disk space and machine will die. My
@@ -518,7 +788,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Script_s_name_space">Script's name space</A></H2></CENTER>
+<CENTER><H1><A NAME="Script_s_name_space">Script's name space</A></H1></CENTER>
<P>
Scripts under <CODE>Apache::Registry</CODE> do not run in package <STRONG>main</STRONG>, they run in a unique name space based on the requested URI. For example,
if your URI is <STRONG>/perl/test.pl</STRONG> the package will be called
@@ -526,147 +796,1200 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Name_collisions_with_Modules_and">Name collisions with Modules and libs</A></H2></CENTER>
+<CENTER><H1><A NAME="Messing_with_INC">Messing with @INC</A></H1></CENTER>
<P>
-To make things clear before we go into details: each child process has its
-own <CODE>%INC</CODE> hash which is used to store information about its compiled modules. The
-keys of the hash are the names of the modules or parameters passed to <CODE>require()</CODE> (<CODE>use()</CODE>). The values are the full or relative paths to these modules/files. Let's
-say we have
-<CODE>my-lib.pl</CODE> and <CODE>MyModule.pm</CODE> both located at <CODE>/home/httpd/perl/my/</CODE>.
+When you <CODE>use(),</CODE> <CODE>require()</CODE> or <CODE>do()</CODE> a
+file, Perl uses a <CODE>@INC</CODE>
+variable, for a list of directories to search for the file. If the file
+that you want to load is not located in one of the listed directories. You
+have to tell Perl where to find the file.
+
+<P>
+In order to <CODE>require()</CODE> a file located at
+<CODE>/home/httpd/perl/examples/test.pl</CODE> you would:
+<UL>
+<P><LI>
<P>
-* <CODE>/home/httpd/perl/my/</CODE> is in the <CODE>@INC</CODE> path at the server startup.
+Use a relative path to one of the directories in the <CODE>@INC</CODE>. Let's say that one of the directories is <CODE>/home/httpd/perl</CODE>.
<P>
-<PRE> require "my-lib.pl";
- use MyModule.pm;
- print $INC{"my-lib.pl"},"\n";
- print $INC{"MyModule.pm"},"\n";
+<PRE> require("examples/test.pl");
</PRE>
<P>
-prints:
+or modify the <CODE>@INC</CODE> on the fly:
<P>
-<PRE> /home/httpd/perl/my/my-lib.pl
- /home/httpd/perl/my/MyModule.pm
+<PRE> use lib qw("examples");
+ require("test.pl");
</PRE>
<P>
-Adding <CODE>use lib</CODE>:
+That's when the script might be called from any place. If you always
+execute the script from the directory it resides in (<CODE>examples</CODE>
+here), you can do:
<P>
-<PRE> use lib qw(.);
- require "my-lib.pl";
- use MyModule.pm;
- print $INC{"my-lib.pl"},"\n";
- print $INC{"MyModule.pm"},"\n";
+<PRE> use lib qw(".");
+ require("test.pl");
</PRE>
<P>
-prints:
+But the latest two snippets would fail the reload by
+<CODE>Apache::StatINC</CODE> module (which helps to automatically reload scripts while developing code)
+since when running under mod_perl, <CODE>@INC</CODE> is being freezed, once the server is up and cannot be updated. The only
+chance to temperarely modify the <CODE>@INC</CODE> is while the script is being loaded and compiled for the first time, and
+when it's done, its value will be reset to the original one. Your only
+chance to change the
+<CODE>@INC</CODE> is to modify it in the startup or Apache configuration files.
+<P><LI>
<P>
-<PRE> my-lib.pl
- MyModule.pm
+You can write a full path to the script:
+
+<P>
+<PRE> require("/home/httpd/perl/examples/test.pl")
</PRE>
<P>
-* <CODE>/home/httpd/perl/my/</CODE> isn't in the <CODE>@INC</CODE> path at the server startup.
+or
<P>
-<PRE> require "my-lib.pl";
- use MyModule.pm;
- print $INC{"my-lib.pl"},"\n";
- print $INC{"MyModule.pm"},"\n";
+<PRE> use lib qw("/home/httpd/perl/examples/");
+ require("test.pl");
</PRE>
<P>
-Wouldn't work, since perl cannot find the modules.
+the latter will fail the reload of <CODE>Apache::StatINC</CODE> as above. The former will set a correct entry into a <CODE>%INC</CODE> variable.
<P>
-Adding <CODE>use lib</CODE>:
+This approach is quite discouraging, since if you want to move this script
+around -- it's quite difficult since you have to modify the path all the
+time. And it can be pretty painful when you move scripts from development
+to production server.
-<P>
-<PRE> use lib qw(.);
- require "my-lib.pl";
- use MyModule.pm;
- print $INC{"my-lib.pl"},"\n";
- print $INC{"MyModule.pm"},"\n";
-</PRE>
<P>
-prints:
+But wait, Graham Barr & Nick Ing-Simmons made a present for you by
+writing the <CODE>FindBin</CODE> module, if you know about this module, you don't need to write a hardcoded
+path. The following snippet does all the work for you:
<P>
-<PRE> my-lib.pl
- MyModule.pm
+<PRE> use FindBin ();
+ use lib "$FindBin::Bin";
+ use MyModule;
</PRE>
<P>
-I'm talking about single server child below!
+It works exactly like with hardcoded path, and it sets a correct
+<CODE>%INC</CODE> entry as if you have used the hardcoded path while using
+<CODE>require().</CODE>
+</UL>
<P>
-Let's look at 3 faulty script's name space related scenarios:
-
-<DL>
-<P><DT><STRONG><A NAME="item_Scenario">Scenario 1</A></STRONG><DD>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
<P>
-First, You can't have 2 identical module names running under the same
-server! Only the first one <CODE>use()</CODE>'d or <CODE>require()</CODE>'d will be compiled into the package, the request to the other identical
-module will be skipped since server will think that it's already compiled.
-It's already in the child's <CODE>%INC</CODE>. (See <A HREF="././status.html#Watching_the_server">Watching the server</A> section to find out how you can know what is loaded and where)
+When you develop plain CGI scripts, you can just change the code, and rerun
+the CGI from your browser. Since the script isn't cached in memory, the
+next time you call it the server starts up a new perl process, which
+recompiles it from scratch. The effects of any modifications you've applied
+are immediately present.
<P>
-So if you have two different <CODE>Foo</CODE> modules in two different directories and two scripts <CODE>script1.pl</CODE> and <CODE>script2.pl</CODE>, placed like:
+The situation is different with <CODE>Apache::Registry</CODE>, since the whole idea is to get maximum performance from the server. By
+default, the server won't spend the time to check whether any included
+library modules have been changed. It assumes that they weren't, thus
+saving a few milliseconds to <CODE>stat()</CODE> the source file (multiplied by however many modules/libraries you are <CODE>use()</CODE>-ing and/or <CODE>require()</CODE>-ing in your script.) The only check that is being done is whether your
+main script has been changed. So if you have only one script that doesn't
+<CODE>use()</CODE> (or <CODE>require()</CODE>) other perl modules (or packages), there is nothing new about it. If
+however, you are developing a script that includes other modules, the files
+you <CODE>use()</CODE> or <CODE>require()</CODE> aren't being checked whether they have been modified.
-<P>
-<PRE> ./perl/tool1/Foo.pm
- ./perl/tool1/tool1.pl
- ./perl/tool2/Foo.pm
- ./perl/tool2/tool2.pl
-</PRE>
<P>
-Where a sample code could be:
+Acknowledging this, how do we get our modperl-enabled server to recognize
+changes in any library modules? Well, there are a couple of techniques:
<P>
-<PRE> ./perl/tool1/tool1.pl
- --------------------
- use Foo;
- print "Content-type: text/html\n\n";
- print "I'm Script number One<BR>\n";
- foo();
- --------------------
-</PRE>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
<P>
-<PRE> ./perl/tool1/Foo.pm
- --------------------
- sub foo{
- print "<B>I'm Tool Number One!</B><BR>\n";
- }
- 1;
- --------------------
-</PRE>
+The simplest approach is to restart the server each time you apply some
+change to your code. See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
+
<P>
-<PRE> ./perl/tool2/tool2.pl
- --------------------
- use Foo;
- print "Content-type: text/html\n\n";
- print "I'm Script number Two<BR>\n";
- foo();
- --------------------
-</PRE>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Using_Apache_StatINC_for_Develo">Using Apache::StatINC for Development Process</A></H2></CENTER>
<P>
-<PRE> ./perl/tool2/Foo.pm
- --------------------
- sub foo{
- print "<B>I'm Tool Number Two!</B><BR>\n";
- }
- 1;
- --------------------
-</PRE>
+After restarting the server about 100 times, you will be tired and will
+look for another solutions. Help comes from the
+<CODE>Apache::StatINC</CODE> module.
+
<P>
-And both scripts call: <CODE>use Foo;</CODE> -- only the first one called will know about <CODE>Foo</CODE>, when you will call the second script it will not know about <CODE>Foo</CODE> at all - it's like you've forgotten to write <CODE>use
-Foo;</CODE>. Run the server in <A HREF="././control.html#Running_server_in_a_single_mode">single server mode</A> to detect this kind of bug immediately.
+<CODE>Apache::StatINC</CODE> reloads <CODE>%INC</CODE> files when updated on disk. When Perl pulls a file via require, it stores
+the filename in the global hash <CODE>%INC</CODE>. The next time Perl tries to require the same file, it sees the file in <CODE>%INC</CODE> and does not reload from disk. This module's handler iterates over <CODE>%INC</CODE> and reloads the file if it has changed on disk.
<P>
-You will see the following in the error_log file:
+To enable this module just add two lines to <CODE>httpd.conf</CODE> file.
<P>
-<PRE> Undefined subroutine
+<PRE> PerlModule Apache::StatINC
+ PerlInitHandler Apache::StatINC
+</PRE>
+<P>
+To be sure it really works, turn on the debug mode on your development box
+with <CODE>PerlSetVar StatINCDebug On</CODE>. You end up with something like:
+
+<P>
+<PRE> PerlModule Apache::StatINC
+ <Location /perl>
+ SetHandler perl-script
+ PerlHandler Apache::Registry::handler
+ Options ExecCGI
+ PerlSendHeader On
+ PerlInitHandler Apache::StatINC
+ PerlSetVar StatINCDebug On
+ </Location>
+</PRE>
+<P>
+Beware that only the modules located in <CODE>@INC</CODE> are being reloaded on change, and you can change the <CODE>@INC</CODE> only before the server has been started (in startup file).
+
+<P>
+Whatever you do in your scripts and modules which are being <CODE>required()</CODE> after the server startup will not have any effect on <CODE>@INC</CODE>. When you do:
+
+<P>
+<PRE> use lib qw(foo/bar);
+</PRE>
+<P>
+the <CODE>@INC</CODE> is being changed only for the time the code is being parsed and compiled.
+When it's over the <CODE>@INC</CODE> is being reset to its original value. To make sure that you have set a
+correct <CODE>@INC</CODE> fetch <A
+HREF="http://www.nowhere.com/perl-status?inc">http://www.nowhere.com/perl-status?inc</A>
+and look at the bottom of the page. (I assume you have configured the <A HREF="././config.html#_perl_status_location">/perl-status location</A>.)
+
+<P>
+Also, notice the following caveat: While ``<CODE>.</CODE>'' is in the <CODE>@INC</CODE> -- perl knows to <CODE>require()</CODE> files relative to the script directory. Once the script was parsed - the
+server doesn't remember the path any more! So you end up with broken entry
+in <CODE>%INC</CODE> like:
+
+<P>
+<PRE> $INC{bar.pl} eq "bar.pl"
+</PRE>
+<P>
+If you want Apache::StatINC to reload your script - modify the <CODE>@INC</CODE>
+at the server startup file! or use a full path in <CODE>require()</CODE> call.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Configuration_Files_Writing_Mo">Configuration Files: Writing, Modifying and Reloading.</A></H2></CENTER>
+<P>
+Checking all the modules in <STRONG>%INC</STRONG> every time can add a large overhead to server response times, and you
+certainly would not want
+<CODE>Apache::StatINC</CODE> module to be enabled in your production site's configuration. But sometimes
+you want to have a configuration file to be reloaded when this updated,
+without restarting the server.
+
+<P>
+This is especially important feature if you have a person that is allowed
+to modify some of the tool configuration, but it's very undesirable for
+this person to telnet to the server to restart it, for either this admin
+person's lack of profeccional skills or because of security reasons -- you
+don't want to give a root password, unless you have to.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H3><A NAME="Writing_Configuration_Files">Writing Configuration Files</A></H3></CENTER>
+<P>
+Since we are talking about configuration files, I would like to jump on
+this and show you some good and bad approaches of configuration file
+writing.
+
+<P>
+If you have a configuration file of just a few variables, it doesn't really
+matter how you do it. But generally this is not a case. Configuration files
+tend to grow as a project grows. It's very relevant to the projects that
+generate HTML files, since the they tend to demand many easily configurable
+parameters, like headers, tails, colors and so on.
+
+<P>
+So let's start from the basic approach that is being mostly deployed by
+many CGI scripts writers. This approach is based on having many variables
+defined in a separate configuration file. For example:
+
+<P>
+<PRE> $cgi_dir = "/home/httpd/perl";
+ $cgi_url = "/perl";
+ $docs_dir = "/home/httpd/docs";
+ $docs_url = "/";
+ $img_dir = "/home/httpd/docs/images";
+ $img_url = "/images";
+ ... many more config params here ...
+ $color_hint = "#777777";
+ $color_warn = "#990066";
+ $color_normal = "#000000";
+</PRE>
+<P>
+Now when we want to use these variables in the mod_perl script we must
+declare them all with help of <CODE>use vars</CODE> in the script, because of the <CODE>use strict;</CODE> pragma, which demands all the variables to be declared if used in the
+script.
+
+<P>
+So we start the script with:
+
+<P>
+<PRE> use strict;
+ use vars qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal
+ );
+</PRE>
+<P>
+This is a nightmare to maintain such a script, especially if not all the
+features were written yet, so you keep adding and reming the names to the
+list. But that's not a big deal.
+
+<P>
+Since we want our code clean, we start the configuration file with
+<CODE>use strict;</CODE> as well, so we have to list the variables here as well. Second list to
+maintain.
+
+<P>
+The moment you will have many scripts, you will get into a problem of
+collisions between configuration files, where one of the best solutions is
+a package declaration, which makes the scripts unique (if you declare
+unique package names of course).
+
+<P>
+The moment you add a package declaration and think that you are done, you
+just realize that the nightmare has just begun. The moment you have
+declared the package, you cannot just <CODE>require()</CODE> the file and
+use the variables, since they now belong to a different package. So you
+have ether to modify all you script to use a fully qualified notation like <CODE>$My::Config::cgi_url</CODE> instead of just <CODE>$cgi_url</CODE> or to import the need variables into a script that is going to use them.
+
+<P>
+Since you don't want extra typing to make the variables fully qualified,
+you would go for importing approach. But your configuration package has to
+export them first. It means that you have to list all the variables again
+and now to keep at least three variable lists updated, when you do some
+changes in the naming of the configuration variables. And that's when you
+have only one script that uses the configuration file, in a general case
+you have many of them. So now our example of config file looks like that.
+
+<P>
+<PRE> package My::Config;
+ use strict;
+
+ BEGIN {
+ use Exporter ();
+
+ @My::HTML::ISA = qw(Exporter);
+ @My::HTML::EXPORT = qw();
+ @My::HTML::EXPORT_OK = qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal);
+ }
+
+ use vars qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal
+ );
+
+ $cgi_dir = "/home/httpd/perl";
+ $cgi_url = "/perl";
+ $docs_dir = "/home/httpd/docs";
+ $docs_url = "/";
+ $img_dir = "/home/httpd/docs/images";
+ $img_url = "/images";
+ ... many more config params here ...
+ $color_hint = "#777777";
+ $color_warn = "#990066";
+ $color_normal = "#000000";
+</PRE>
+<P>
+And in the code:
+
+<P>
+<PRE> use strict;
+ use My::Config qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal
+ );
+ use vars qw($cgi_dir $cgi_url $docs_dir $docs_url
+ ... many more config params here ....
+ $color_hint $color_warn $color_normal
+ );
+</PRE>
+<P>
+But as we know this approach is especially bad in a context of mod_perl
+usage, since exported variables add a memory overhead. The more variables
+are being exported the more memory you use. Now as usual we rememeber to
+multiply this overhead by number of the servers we are going to run and we
+receive a pretty big number, which could be used to run a few more servers
+instead.
+
+<P>
+As a matter of fact things aren't so horrible, since you can group your
+variables, and call the groups by special names called tags, which can
+later be used as arguments to the <CODE>import()</CODE> or
+<CODE>use().</CODE> You probably familiar with:
+
+<P>
+<PRE> use CGI qw(:standard :html);
+</PRE>
+<P>
+We can implement it quite easily, with help of <CODE>exporter_tags()</CODE>
+and <CODE>export_ok_tags()</CODE> from <CODE>Exporter</CODE>. For example:
+
+<P>
+<PRE> BEGIN {
+ use Exporter ();
+ use vars qw( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+ @ISA = qw(Exporter);
+ @EXPORT = qw();
+ @EXPORT_OK = qw();
+
+ %EXPORT_TAGS = (
+ vars => [qw($fname $lname)],
+ subs => [qw(reread_conf untaint_path)],
+ );
+ Exporter::export_ok_tags('vars');
+ Exporter::export_ok_tags('subs');
+ }
+</PRE>
+<P>
+Yes, you export subroutines exactly like variables, since what's actually
+being exported is a symbol. The definition of these subroutines is not
+shown here.
+
+<P>
+In your code now you can write:
+
+<P>
+<PRE> use My::Config qw(:subs :vars);
+</PRE>
+<P>
+Regarding groups of groups. Like the <CODE>:all</CODE> tag from <CODE>CGI.pm</CODE>, which is a group tag of all other groups. It will require a little more
+magic from your side, but you can always save your time and look up the
+solution inside the code of <CODE>CGI.pm</CODE>. It's just a matter of a little code to expand all the groups recursively.
+
+<P>
+After going through a pain of maintaining a list of variables in a big
+project with a huge configuration file (more than 100 variables) and many
+files actually using them, I have come up with a much simpler solution,
+using a single hash, and having all the variables kept inside. Now my
+configuration file looks like:
+
+<P>
+<PRE> package My::Config;
+ use strict;
+
+ BEGIN {
+ use Exporter ();
+
+ @My::Config::ISA = qw(Exporter);
+ @My::Config::EXPORT = qw();
+ @My::Config::EXPORT_OK = qw(%c);
+ }
+
+ use vars qw(%c);
+
+ %c =
+ (
+ dir => {
+ cgi => "/home/httpd/perl",
+ docs => "/home/httpd/docs",
+ img => "/home/httpd/docs/images",
+ },
+ url => {
+ cgi => "/perl",
+ docs => "/",
+ img => "/images",
+ },
+ color => {
+ hint => "#777777",
+ warn => "#990066",
+ normal => "#000000",
+ },
+ );
+</PRE>
+<P>
+A good perl style suggests keeping a comma at the end of lists. That's
+because additional items are tend to be added to the end of the list, and
+when you keep a last comma in place, you never have to remember to add one
+when you add a new item.
+
+<P>
+So now the script looks like:
+
+<P>
+<PRE> use strict;
+ use My::Config qw(%c);
+ use vars qw(%c)
+ print "Content-type: text/plain\n\n";
+ print "My url docs root: $c{url}{docs}\n";
+</PRE>
+<P>
+Do you see the difference? The whole mess has gone, there is only one
+variable to worry about.
+
+<P>
+So far so good, but let's make it even better. I would like to get rid of <CODE>Exporter</CODE> stuff at all. I remove all the exporting code so my config file now looks
+like:
+
+<P>
+<PRE> package My::Config;
+ use strict;
+ use vars qw(%c);
+
+ %c =
+ (
+ dir => {
+ cgi => "/home/httpd/perl",
+ docs => "/home/httpd/docs",
+ img => "/home/httpd/docs/images",
+ },
+ url => {
+ cgi => "/perl",
+ docs => "/",
+ img => "/images",
+ },
+ color => {
+ hint => "#777777",
+ warn => "#990066",
+ normal => "#000000",
+ },
+ );
+</PRE>
+<P>
+And the code
+
+<P>
+<PRE> use strict;
+ use My::Config ();
+ print "Content-type: text/plain\n\n";
+ print "My url docs root: $My::Config::c{url}{docs}\n";
+</PRE>
+<P>
+Since we still want to save us lots of typing, since now we need to use a
+fully qualified notation like in <CODE>$My::Config::c{url}{docs}</CODE>, let's use a magical perl's aliasing feature. I'll modify the code to be:
+
+<P>
+<PRE> use strict;
+ use My::Config ();
+ use vars qw(%c);
+ *c = \%My::Config::c;
+ print "Content-type: text/plain\n\n";
+ print "My url docs root: $c{url}{docs}\n";
+</PRE>
+<P>
+I have alised <CODE>*c</CODE> glob with <CODE>\%My::Config::c</CODE> hash reference. From now on <CODE>%My::Config::c</CODE> and <CODE>%c</CODE> are the same hash. You can read from or modify any of them, both variables
+are the same one.
+
+<P>
+Just one last little notice. Sometimes you see a lot of redundance in the
+configuration variables, like:
+
+<P>
+<PRE> $cgi_dir = "/home/httpd/perl";
+ $docs_dir = "/home/httpd/docs";
+ $img_dir = "/home/httpd/docs/images";
+</PRE>
+<P>
+Now if you want to move the base path <CODE>"/home/httpd"</CODE> into a new place, it demands lots of typing. Of course the solution is:
+
+<P>
+<PRE> $base = "/home/httpd";
+ $cgi_dir = "$base/perl";
+ $docs_dir = "$base/docs";
+ $img_dir = "$base/docs/images";
+</PRE>
+<P>
+But you cannot do the same trick with hash. This wouldn't work:
+
+<P>
+<PRE> %c =
+ (
+ base => "/home/httpd",
+ dir => {
+ cgi => "$base/perl",
+ docs => "$base/docs",
+ img => "$base/docs/images",
+ },
+ );
+</PRE>
+<P>
+But nothing stops us from adding additional variables, which are lexically
+scoped with <CODE>my().</CODE> The following code is correct.
+
+<P>
+<PRE> my $base = "/home/httpd";
+ %c =
+ (
+ dir => {
+ cgi => "$base/perl",
+ docs => "$base/docs",
+ img => "$base/docs/images",
+ },
+ );
+</PRE>
+<P>
+We have just learned how to make configuration files easily maintainable,
+and how to save memory by avoiding variables exporting into a script's
+namespace.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H3><A NAME="Reloading_Configuration_Files">Reloading Configuration Files</A></H3></CENTER>
+<P>
+Now back to the task of dynamically reloading of configuration files.
+
+<P>
+First, lets see a simple case, when we just have to watch after a simple
+configuration file, like this one. Imagine a script that tells who is patch
+pumkin of the current perl release.
+
+<P>
+Sidenote: <jargon> A humourous term for the token - the object
+(notional or real) that gives its possessor (the ``pumpking'' or the
+``pumpkineer'') exclusive access to something, e.g. applying patches to a
+master copy of source (for which the pumpkin is called a ``patch
+pumpkin'').
+
+<P>
+<PRE> use CGI ();
+ use strict;
+
+ my $fname = "Larry";
+ my $lname = "Wall";
+ my $q = new CGI;
+
+ print $q->header(-type=>'text/html');
+ print $q->p("$fname $lname holds the patch pumpkin
+ for this perl release.");
+</PRE>
+<P>
+The script has a hardcoded value for the name. It's very simple: initialize
+the CGI object, print the proper HTTP header and tell the world who is the
+current patch pumpkin.
+
+<P>
+When the patch pumkin changes we don't want to modify the script.
+Therefore, we put the <CODE>$fname</CODE> and <CODE>lname</CODE> variables into a configuration file.
+
+<P>
+<PRE> $fname = "Gurusamy";
+ $lname = "Sarathy";
+ 1;
+</PRE>
+<P>
+Please notice that there is no package declaration in the above file, so
+the code will be evaluated in the caller's package or in the
+<CODE>main::</CODE> package if none was declared. It means that variables
+<CODE>$fname</CODE> and <CODE>$lname</CODE> will override (or initialize if they weren't yet) the variables with the
+same names in the caller's namespace. This works for global variables only
+-- you cannot update lexically defined (with <CODE>my())</CODE> variables
+by this technique.
+
+<P>
+You have started the server and everything is working properly. After a
+while you decide to modify the configuration. How do you let your running
+know, that the configuration was modified, without restarting the server,
+remember we are in production and server restarting can be quite expensive
+for us. ? One of the simplest solutions is to poll the file's modification
+time by calling <CODE>stat()</CODE> before the script starts to do a real
+work, and if we see that the file was updated, we force a reconfiguration
+of the variables located in this file. We will call the function that
+reloads the configuration <CODE>reread_conf()</CODE> and it accepts a
+single argument, which is a relative path to the configuration file.
+
+<P>
+If your CGI script is being invoked under <CODE>Apache::Registry</CODE> handler, you can put the configuration file in the same directory as a
+script or below it and path a relative path to the file, since
+<CODE>Apache::Registry</CODE> calls a <CODE>chdir()</CODE> to the script's directory before it starts the
+script's execution. Otherwise you would have to make sure that the file
+will be found. <CODE>do()</CODE> does search the <CODE>@INC</CODE>
+libraries.
+
+<P>
+<PRE> use vars qw(%MODIFIED);
+ sub reread_conf{
+ my $file = shift;
+ return unless $file;
+ return unless -e $file and -r _;
+ unless ($MODIFIED{$file} and $MODIFIED{$file} == -M _){
+ my $return;
+ unless ($return = do $file) {
+ warn "couldn't parse $file: $@" if $@;
+ warn "couldn't do $file: $!" unless defined $return;
+ warn "couldn't run $file" unless $return;
+ }
+ $MODIFIED{$file} = -M _; # Update the MODIFICATION times
+ }
+ } # end of reread_conf
+</PRE>
+<P>
+We use <CODE>do()</CODE> to reload the code in this file and not
+<CODE>require()</CODE> because, <CODE>do()</CODE> reloads the file
+unconditionally, while <CODE>require()</CODE> will not load the file if it
+was already loaded in one of the previous requests, since there will be an
+entry in the <CODE>%INC</CODE> where the key is the name of the file and the value the path to it. That's
+how Perl keeps track of loaded files and saves overhead of reloading when
+it has to load the same file again. You generally doesn't notice that with
+plain perl scripts, but in mod_perl it's being used all the time (since the
+same script is being reloaded all the time, and all the
+<CODE>require()'s</CODE> files are already loaded after a first request for
+each process.
+
+<P>
+Nevertheless, <CODE>do()</CODE> keeps track of the current filename for
+error messages, searches the <CODE>@INC</CODE> libraries, updates the <CODE>%INC</CODE> if the file is found.
+
+<P>
+To explain all the possible warnings the script emits if something went
+wrong with operation, it's just for a matter of completeness. Generally you
+would do all these checks. If <CODE>do()</CODE> cannot read the file, it returns <CODE>undef</CODE> and sets <CODE>$!</CODE> to the error. If <CODE>do()</CODE> can read the file but cannot compile it, it returns <CODE>undef</CODE> and sets an error message in <CODE>$@</CODE>. If the file is successfully compiled, <CODE>do()</CODE>
+returns the value of the last expression evaluated.
+
+<P>
+Also the configuration file can be broken if someone has incorrectly
+modified it. We don't want the service to go broken, because of that. We
+just trap the possible failure to <CODE>do()</CODE> the file and ignore the
+changes, by the resetting the modification time. It might be a good idea to
+send an email to system administrator about the problem.
+
+<P>
+Notice however, that since <CODE>do()</CODE> updates the <CODE>%INC</CODE> like <CODE>require()</CODE> does, if you are using <CODE>Apache::StatINC</CODE>, it will attempt to reload this file before the <CODE>reread_conf()</CODE>
+call, so if it the file wouldn't compile the request would be aborted. This
+shouldn't be a problem since <CODE>Apache::StatINC</CODE> shouldn't be used in production (because it slows things down by
+<CODE>stat()'ing</CODE> all the files listed in <CODE>%INC</CODE>).
+
+<P>
+Note that we assume that the entire purpose of this function is to reload
+the configuration if that was changed, that's why there is no possible
+failure for this function. If something goes wrong we just return. This
+approach would be incorrect if you are going to initialize the variables
+thru this method on the first invocation of the script. If you do, you will
+want to replace each occurence of <CODE>return()</CODE> and
+<CODE>warn()</CODE> with <CODE>die().</CODE>
+
+<P>
+I used the above approach when I've had a huge configuration file that was
+loaded only once at the server startup, and another little configuration
+file that included only a few variables that could be updated by hand or
+through the web interface, and those variables were duplicates in the main
+config file.
+
+<P>
+So if webmaster breaks the syntax in this dynamic file while updating it by
+hand, it wouldn't affect the main configuration file (which was
+write-protected) and so the proper executing of the programs. Soon we will
+see a simple web interface which allows to modify the configuration file
+without actually breaking it.
+
+<P>
+A sample script using the presented subroutine would be:
+
+<P>
+<PRE> use vars qw(%MODIFIED $fname $lname);
+ use CGI ();
+ use strict;
+
+ my $q = new CGI;
+ print $q->header(-type=>'text/plain');
+ my $config_file = "./config.pl";
+ reread_conf($config_file);
+ print $q->p("$fname $lname holds the patch pumpkin
+ for this perl release.");
+
+ sub reread_conf{
+ my $file = shift;
+ return unless $file;
+ return unless -e $file and -r _;
+ unless ($MODIFIED{$file} and $MODIFIED{$file} == -M _){
+ my $return;
+ unless ($return = do $file) {
+ warn "couldn't parse $file: $@" if $@;
+ warn "couldn't do $file: $!" unless defined $return;
+ warn "couldn't run $file" unless $return;
+ }
+ $MODIFIED{$file} = -M _; # Update the MODIFICATION times
+ }
+ } # end of reread_conf
+</PRE>
+<P>
+Remember that you should be using <CODE>(stat $file)[9]</CODE> instead of <CODE>-M
+$file</CODE> if you are modifying the <CODE>$^M</CODE> variable. In some of my scripts, I reset <CODE>$^M</CODE> to the time of the script invocation with
+<CODE>"$^M = time()"</CODE>, so I can perform <CODE>-M</CODE> and alike (<CODE>-A</CODE>, <CODE>-C</CODE>) file status testings relative to the script invocation time and not the
+time the process was started.
+
+<P>
+If your configuration file is more sophisticated and it declares a package
+and exports variables, the above code will work just as well. Even if you
+think that you will have to re-import() variables, they are just there and
+when do recompiles the code, the originally imported variables get updates
+with the values from the reloaded code.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H3><A NAME="Dynamically_updating_configurati">Dynamically updating configuration files</A></H3></CENTER>
+<P>
+The CGI script below allows a system administrator, to dynamically update
+configuration file through the web interface. Combining this with the code
+we have just showed to reload the modified files, you get a complete suite
+of dynamically reconfigurable system which doesn't require server restart
+and can be performed from any machine having just a web interface (a simple
+browser connected to the Internet).
+
+<P>
+Let's say you have a configuration file like:
+
+<P>
+<PRE> package MainConfig;
+
+ use strict;
+ use vars qw(%c);
+
+ %c = (
+ name => "Larry Wall",
+ release => "5.000",
+ comments => "Adding more ways to do the same thing :)",
+
+ other => "More config values",
+
+ hash => { foo => "bar",
+ fooo => "barr",
+ },
+
+ array => [qw( a b c)],
+
+ );
+</PRE>
+<P>
+You want to make the variables <CODE>name</CODE>, <CODE>release</CODE> and <CODE>comments</CODE>
+dynamically configurable. Which means that you want to have a web interface
+with input form that allows to modify these variables. Once modified you
+want to update the configuration file and propogate the changes to all the
+currently running processes. Quite a simple task.
+
+<P>
+Let's see the main stages of this algorithm. Create a form with preset
+current values of the variables. Let the administrator to modify and submit
+the changes. Validate that the submitted information is correctly formatted
+(numeric fields should carry numbers, literal - words and etc). Update the
+configuration file. Update the modified value in the memory of the current
+process. Present the form as before but with updated fields if any.
+
+<P>
+The only part that seems to be complicated to implement is a configuration
+file update. For a few reasons. If updating the file breaks it - the whole
+service wouldn't work. If the file is very big and includes comments and
+complex data structures, parsing the file can be quite a challenge.
+
+<P>
+So let's simplify the task. We wouldn't touch the original configuration
+file, if all we want is to updated a few variables, why don't we create a
+little configuration file with just a variables that can be modified
+throught the web interface and overwrite it each time there is something to
+be changed. This way we don't have to parse the file, before updating it.
+And if the main configuration file is going to be changed, we don't care
+about it -- since we aren't dependent on it any more.
+
+<P>
+Moreover, we will have these dynamically updated variables duplicated, they
+will show up in both places - in the main file and in the dynamic file. We
+do it, to simplify the maintainance. When a new release is being installed
+the dynamic configuration file shouldn't exist at all. It'll be created
+only after a first update. The only change it requires to the main code is
+to add a snippet of code to load this file if it exists and was changed as
+we just saw.
+
+<P>
+This additional code must be executed after the main configuration file is
+being loaded. That way the updated variables would override the default
+values in the main file.
+
+<P>
+META: extend on the comments:
+
+<P>
+<PRE> # remember to run this code under taint mode
+
+ use strict;
+ use vars qw($q %c $dynamic_config_file %vars_to_change %validation_rules);
+
+ use CGI ();
+
+ use lib qw(.);
+ use MainConfig ();
+ *c = \%MainConfig::c;
+
+ $dynamic_config_file = "./config.pl";
+
+ # load the dynamic conf file if exists, and override the default
+ # values from the main config file
+ do $dynamic_config_file if -e $dynamic_config_file and -r _;
+
+ # fields that can be changed and their titles
+ %vars_to_change =
+ (
+ 'name' => "Patch Pumkin's Name",
+ 'release' => "Current Perl Release",
+ 'comments' => "Release Comments",
+ );
+
+ %validation_rules =
+ (
+ 'name' => sub { $_[0] =~ /^[\w\s\.]+$/; },
+ 'release' => sub { $_[0] =~ /^\d+\.[\d_]+$/; },
+ 'comments' => sub { 1; },
+ );
+
+ $q = new CGI;
+ print $q->header(-type=>'text/html'),
+ $q->start_html();
+
+ my %updates = ();
+
+ # We always rewrite the dynamic config file, so we want all the
+ # vars to be passed but to save the time we will only do checking
+ # of vars that that was changed the rest will be retrieved from
+ # the 'prev_foo' values
+ foreach (keys %vars_to_change) {
+ # copy var so we can modify it
+ my $new_val = $q->param($_) || '';
+
+ # strip a possible ^M char (DOS/WIN)
+ $new_val =~ s/\cM//g;
+
+ # push to hash if was changed
+ $updates{$_} = $new_val
+ if defined $q->param("prev_".$_) and $new_val ne $q->param("prev_".$_);
+ }
+
+ # Notice that we cannot trust the previous values of the variables
+ # since they were presented to user as hidden form variables, and
+ # of course user can mangle those. In our case we don't care since
+ # it cannot make any damage, since as you will see in a minute we
+ # verify each variable by the rules we define.
+
+ # Process if there is something to process. Will be not called if
+ # it's invoked a first time to diplay the form or when the form
+ # was submitted but the values weren't modified (we know that by
+ # comparing with the previous values of the variables, which are
+ # the hidden fields in the form)
+
+ # process and update the values if valid
+ process_change_config(%updates) if %updates;
+
+ # print the update form
+ conf_modification_form();
+
+ # update the config file but first validate that the values are correct ones
+ #########################
+ sub process_change_config{
+ my %updates = @_; # dereference
+
+ # we will list here all the malformatted vars
+ my %malformatted = ();
+
+ print $q->b("Trying to validate these values<BR>");
+ foreach (keys %updates) {
+ print "<DT><B>$_</B> => <PRE>$updates{$_}</PRE>";
+
+ # now we have to handle each var to be changed very very carefully
+ # since this file goes immediately into production!
+ $malformatted{$_} = delete $updates{$_}
+ unless $validation_rules{$_}->($updates{$_});
+
+ } # end of foreach my $var (keys %updates)
+
+ # print warnings if there are any invalid changes
+ print $q->hr,
+ $q->p($q->b(qq{Warning! These variables were attempted to be
+ changed, but found malformed, thus the original
+ value will be preserved.})
+ ),
+ join(",<BR>",
+ map { $q->b($vars_to_change{$_}) . " : $malformatted{$_}\n"
+ } keys %malformatted)
+ if %malformatted;
+
+ # Now complete the vars that weren't changed from the
+ # $q->param('prev_var') values
+ map { $updates{$_} = $q->param('prev_'.$_) unless exists $updates{$_}
+ } keys %vars_to_change;
+
+ # Now we have all the data that should be written into dynamic
+ # config file
+
+ # escape single quotes "'" while creating a file
+ my $content = join "\n",
+ map { $updates{$_} =~ s/(['\\])/\\$1/g;
+ '$c{' . $_ . "} = '" . $updates{$_} . "';\n"
+ } keys %updates;
+
+ # now add '1;' to make require() happy
+ $content .= "\n1;";
+
+ # keep the dummy result in $r so it'll not complain
+ eval {my $res = $content};
+ if ($@) {
+ print qq{Warning! Something went wrong with config file
+ generation!<P> The error was : <BR><PRE>$@</PRE>};
+ return;
+ }
+
+ print $q->hr;
+
+ # overwrite the dynamic config file
+ use Symbol ();
+ my $fh = Symbol::gensym();
+ open $fh, ">$dynamic_config_file.bak"
+ or die "Can't open the $dynamic_config_file.bak for writing :$! \n";
+ flock $fh,2; # exclusive lock
+ seek $fh,0,2; # rewind to the start
+ truncate $fh, 0; # the file might shrink!
+ print $fh $content;
+ close $fh;
+
+ # OK, now we make a real file
+ rename "$dynamic_config_file.bak",$dynamic_config_file;
+
+ # rerun it to update variables in the current process! Note that
+ # it wouldn't update the variables in other processes. A special
+ # code that watches the timestamps on the config file will do this
+ # work for each process. Since the next invocation will update the
+ # configuration anyway, why do we need to load it here? The reason
+ # is simple, since we are going to fill form's input fields, with
+ # the updated data.
+ do $dynamic_config_file;
+
+ } # end sub process_change_config
+
+ ##########################
+ sub conf_modification_form{
+
+ print $q->center($q->h3("Update Form"));
+
+ print $q->hr,
+ $q->p(qq{This form allows you to dynamically update the current
+ configuration. You don\'t need to restart the server in
+ order for changes to take an effect}
+ );
+
+ # set the previous settings into the form's hidden fields, so we
+ # know whether we have to do some changes or not
+ map {$q->param("prev_$_",$c{$_}) } keys %vars_to_change;
+
+ # raws for the table, go into the form
+ my @configs = ();
+
+ # prepare one textfield entries
+ push @configs,
+ map {
+ $q->td(
+ $q->b("$vars_to_change{$_}:"),
+ ),
+ $q->td(
+ $q->textfield(-name => $_,
+ -default => $c{$_},
+ -override => 1,
+ -size => 20,
+ -maxlength => 50,
+ )
+ ),
+ } qw(name release);
+
+ # prepare multiline textarea entries
+ push @configs,
+ map {
+ $q->td(
+ $q->b("$vars_to_change{$_}:"),
+ ),
+ $q->td(
+ $q->textarea(-name => $_,
+ -default => $c{$_},
+ -override => 1,
+ -rows => 10,
+ -columns => 50,
+ -wrap => "HARD",
+ )
+ ),
+ } qw(comments);
+
+ print $q->startform('POST',$q->url),"\n",
+ $q->center($q->table(map {$q->Tr($_),"\n",} @configs),
+ $q->submit('','Update!'),"\n",
+ ),
+ map ({$q->hidden("prev_".$_, $q->param("prev_".$_))."\n" }
+ keys %vars_to_change), # hidden previous values
+ $q->br,"\n",
+ $q->endform,"\n",
+ $q->hr,"\n",
+ $q->end_html;
+
+ } # end sub conf_modification_form
+</PRE>
+<P>
+Once updated the script generates a file like:
+
+<P>
+<PRE> $c{release} = '5.6';
+
+ $c{name} = 'Gurusamy Sarathy';
+
+ $c{comments} = 'Perl rules the world!';
+
+ 1;
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="Reloading_handlers">Reloading handlers</A></H2></CENTER>
+<P>
+If you want to reload perlhandler on each invocation, the following trick
+will do it:
+
+<P>
+<PRE> PerlHandler "sub { do 'MyTest.pm'; MyTest::handler(shift) }"
+</PRE>
+<P>
+<CODE>do()</CODE> will reload <CODE>MyTest.pm</CODE> every request.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Name_collisions_with_Modules_and">Name collisions with Modules and libs</A></H1></CENTER>
+<P>
+To make things clear before we go into details: each child process has its
+own <CODE>%INC</CODE> hash which is used to store information about its compiled modules. The
+keys of the hash are the names of the modules or parameters passed to <CODE>require()</CODE> (<CODE>use()</CODE>). The values are the full or relative paths to these modules/files. Let's
+say we have
+<CODE>my-lib.pl</CODE> and <CODE>MyModule.pm</CODE> both located at <CODE>/home/httpd/perl/my/</CODE>.
+
+<UL>
+<P><LI><STRONG><A NAME="item__home_httpd_perl_my_is_in_the_">/home/httpd/perl/my/ is in the @INC at the server startup.</A></STRONG>
+<P>
+<PRE> require "my-lib.pl";
+ use MyModule.pm;
+ print $INC{"my-lib.pl"},"\n";
+ print $INC{"MyModule.pm"},"\n";
+</PRE>
+<P>
+prints:
+
+<P>
+<PRE> /home/httpd/perl/my/my-lib.pl
+ /home/httpd/perl/my/MyModule.pm
+</PRE>
+<P>
+Adding <CODE>use lib</CODE>:
+
+<P>
+<PRE> use lib qw(.);
+ require "my-lib.pl";
+ use MyModule.pm;
+ print $INC{"my-lib.pl"},"\n";
+ print $INC{"MyModule.pm"},"\n";
+</PRE>
+<P>
+prints:
+
+<P>
+<PRE> my-lib.pl
+ MyModule.pm
+</PRE>
+<P><DT><STRONG><A NAME="item__home_httpd_perl_my_">/home/httpd/perl/my/ isn't in the @INC path at the server startup.</A></STRONG><DD>
+<P>
+<PRE> require "my-lib.pl";
+ use MyModule.pm;
+ print $INC{"my-lib.pl"},"\n";
+ print $INC{"MyModule.pm"},"\n";
+</PRE>
+<P>
+wouldn't work, since perl cannot find the modules.
+
+<P>
+Adding <CODE>use lib</CODE>:
+
+<P>
+<PRE> use lib qw(.);
+ require "my-lib.pl";
+ use MyModule.pm;
+ print $INC{"my-lib.pl"},"\n";
+ print $INC{"MyModule.pm"},"\n";
+</PRE>
+<P>
+prints:
+
+<P>
+<PRE> my-lib.pl
+ MyModule.pm
+</PRE>
+</UL>
+<P>
+I'm talking about single child below!
+
+<P>
+Let's look at 3 faulty script's name space related scenarios:
+
+<DL>
+<P><DT><STRONG><A NAME="item_Scenario">Scenario 1</A></STRONG><DD>
+<P>
+First, You can't have 2 identical module names running under the same
+server! Only the first one <CODE>use()</CODE>'d or <CODE>require()</CODE>'d will be compiled into the package, the request to the other identical
+module will be skipped since server will think that it's already compiled.
+It's already in the child's <CODE>%INC</CODE>. (See <A HREF="././status.html#Watching_the_server">Watching the server</A> section to find out how you can know what is loaded and where)
+
+<P>
+So if you have two different <CODE>Foo</CODE> modules in two different directories and two scripts <CODE>script1.pl</CODE> and <CODE>script2.pl</CODE>, placed like:
+
+<P>
+<PRE> ./perl/tool1/Foo.pm
+ ./perl/tool1/tool1.pl
+ ./perl/tool2/Foo.pm
+ ./perl/tool2/tool2.pl
+</PRE>
+<P>
+Where a sample code could be:
+
+<P>
+<PRE> ./perl/tool1/tool1.pl
+ --------------------
+ use Foo;
+ print "Content-type: text/html\n\n";
+ print "I'm Script number One<BR>\n";
+ foo();
+ --------------------
+</PRE>
+<P>
+<PRE> ./perl/tool1/Foo.pm
+ --------------------
+ sub foo{
+ print "<B>I'm Tool Number One!</B><BR>\n";
+ }
+ 1;
+ --------------------
+</PRE>
+<P>
+<PRE> ./perl/tool2/tool2.pl
+ --------------------
+ use Foo;
+ print "Content-type: text/html\n\n";
+ print "I'm Script number Two<BR>\n";
+ foo();
+ --------------------
+</PRE>
+<P>
+<PRE> ./perl/tool2/Foo.pm
+ --------------------
+ sub foo{
+ print "<B>I'm Tool Number Two!</B><BR>\n";
+ }
+ 1;
+ --------------------
+</PRE>
+<P>
+And both scripts call: <CODE>use Foo;</CODE> -- only the first one called will know about <CODE>Foo</CODE>, when you will call the second script it will not know about <CODE>Foo</CODE> at all - it's like you've forgotten to write <CODE>use
+Foo;</CODE>. Run the server in <A HREF="././control.html#Running_server_in_a_single_mode">single server mode</A> to detect this kind of bug immediately.
+
+<P>
+You will see the following in the error_log file:
+
+<P>
+<PRE> Undefined subroutine
&Apache::ROOT::perl::tool2::tool2_2epl::foo called at
/home/httpd/perl/tool2/tool2.pl line 4.
</PRE>
@@ -829,7 +2152,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="More_package_name_related_issues">More package name related issues</A></H2></CENTER>
+<CENTER><H1><A NAME="More_package_name_related_issues">More package name related issues</A></H1></CENTER>
<P>
If you have the following:
@@ -844,26 +2167,82 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H2></CENTER>
+<CENTER><H1><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H1></CENTER>
+<P>
+<CODE>Apache::Registry</CODE> scripts cannot contain <CODE>__END__</CODE> or <CODE>__DATA__</CODE>
+tokens.
+
+<P>
+Why? Because <CODE>Apache::Registry</CODE> scripts are being wrapped into a subroutine called <CODE>handler</CODE>, like the script at URI <CODE>/perl/test.pl</CODE>:
+
+<P>
+<PRE> print "Content-type: text/plain\n\n";
+ print "Hi";
+</PRE>
+<P>
+When the script is being executed under <CODE>Apache::Registry</CODE> handler, it actually becomes:
+
+<P>
+<PRE> package Apache::ROOT::perl::test_2epl;
+ use Apache qw(exit);
+ sub handler {
+ print "Content-type: text/plain\n\n";
+ print "Hi";
+ }
+</PRE>
+<P>
+So if you happen to put an <CODE>__END__</CODE> tag, like:
+
+<P>
+<PRE> print "Content-type: text/plain\n\n";
+ print "Hi";
+ __END__
+ Some text that wouldn't be normally executed
+</PRE>
<P>
-<CODE>Apache::Registry</CODE> scripts cannot contain __END__ or __DATA__ tokens.
+it will be turned into:
<P>
+<PRE> package Apache::ROOT::perl::test_2epl;
+ use Apache qw(exit);
+ sub handler {
+ print "Content-type: text/plain\n\n";
+ print "Hi";
+ __END__
+ Some text that wouldn't be normally executed
+ }
+</PRE>
+<P>
+and you try to execute this script, you will receive the following warning:
+
+<P>
+<PRE> Missing right bracket at q line 4, at end of line
+</PRE>
+<P>
+And that's clear, Perl cuts everything after <CODE>__END__</CODE> tag. The same thing applies to <CODE>__DATA__</CODE> tag.
+
+<P>
+Also, rememeber that whatever applies to <CODE>Apache::Registry</CODE> scripts, in most cases applies to <CODE>Apache::PerlRun</CODE> scripts.
+
+<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Output_from_system_calls">Output from system calls</A></H2></CENTER>
+<CENTER><H1><A NAME="Output_from_system_calls">Output from system calls</A></H1></CENTER>
<P>
Output of <CODE>system()</CODE>, <CODE>exec()</CODE>, and <CODE>open(PIPE,"|program")</CODE> calls will not be sent to the browser unless your Perl was configured with
<CODE>sfio</CODE>.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Using_format_">Using format()</A></H2></CENTER>
+<CENTER><H1><A NAME="Using_format_and_write_">Using format() and write()</A></H1></CENTER>
<P>
-Currently possible only if you have perl compiled with <CODE>sfio</CODE>.
+The Perl <CODE>tie()'d</CODE> filehandle interface is not complete,
+<CODE>format()</CODE> / <CODE>write()</CODE> are ones of the missing
+pieces. If you configure Perl with
+<CODE>sfio</CODE>, <CODE>write()</CODE> and <CODE>format()</CODE> should work just fine.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Using_exit_">Using exit()</A></H2></CENTER>
+<CENTER><H1><A NAME="Using_exit_">Using exit()</A></H1></CENTER>
<P>
Perl's <STRONG>exit()</STRONG> built-in function cannot be used in mod_perl scripts. Calling it causes the
server child to exit (which makes the whole idea of using mod_perl
@@ -908,58 +2287,285 @@
<CODE>$r-&gt;child_terminate</CODE> (which sets the internal
<CODE>MaxRequestsPerChild</CODE> so the child will exit).
+<P>
+You can accomplish this in two ways - in the <CODE>Apache::Registry</CODE> script:
+
+<P>
+<PRE> Apache->request->child_terminate;
+</PRE>
+<P>
+in httpd.conf:
+
+<P>
+<PRE> PerlFixupHandler "sub { shift->child_terminate }"
+</PRE>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Running_from_shell">Running from shell</A></H1></CENTER>
+<P>
+Your scripts <STRONG>will not</STRONG> run from the command line (yet) unless you use <CODE>CGI::Switch</CODE> or <CODE>CGI.pm</CODE> and perl 5.004+ and do not make any direct calls to <CODE>Apache-&gt;methods</CODE>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="I_O_is_different">I/O is different</A></H1></CENTER>
+<P>
+If you are using Perl 5.004 or better, most CGI scripts can run under
+mod_perl untouched. If you're using 5.003, Perl's built-in <CODE>read()</CODE>
+and <CODE>print()</CODE> functions do not work as they do under CGI. If you're using <CODE>CGI.pm</CODE>, use <CODE>$query-&gt;print</CODE> instead of plain 'ol
+<CODE>print()</CODE>.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Special_Perl_Variables">Special Perl Variables</A></H1></CENTER>
+<P>
+A special Perl variables like <CODE>$|</CODE> (buffering), <CODE>$^T</CODE> (time), <CODE>$^W</CODE>
+(warnings), <CODE>$/</CODE> (input record separator), <CODE>$\</CODE> (output record separator) and many more are all global variables. It means
+that you cannot localize them with <CODE>my().</CODE> Only
+<CODE>local()</CODE> is permitted to do that. Since the child server
+doesn't quit - if in one of your scripts you modify the global varible
+it'll be changed for the rest of the process' life and would affect all the
+scripts that will be executed under the same process.
+
+<P>
+Remembering this you should never write a code like this. We will exercise
+the input record separator variable. If you undefine this variable, a
+diamond operator will suck the whole file at once.
+
+<P>
+<PRE> $/ = undef;
+ open IN, "file" ....
+ # slurp it all inside a variable
+ $all_the_file = <IN>;
+</PRE>
+<P>
+The proper way is to have a <CODE>local()</CODE> keyword before the special
+variable is being changed, like:
+
+<P>
+<PRE> local $/ = undef;
+ open IN, "file" ....
+ # slurp it all inside a variable
+ $all_the_file = <IN>;
+</PRE>
+<P>
+But there is a little catch. <CODE>local()</CODE> will propogate the
+changed value to any of the code below it and would be in effect untill the
+script will be finished, if not modified in some other place.
+
+<P>
+A cleaner approach is to embrace the whole code that is being effected by
+the modificated variable in to a block, like:
+
+<P>
+<PRE> {
+ $/ = undef;
+ open IN, "file" ....
+ # slurp it all inside a variable
+ $all_the_file = <IN>;
+ }
+</PRE>
+<P>
+That way when Perl leaves the block, it restores the original value of the <CODE>$/</CODE> variable. So you should worry about this variable anywhere else in scope of
+your program.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Generating_correct_HTTP_Headers">Generating correct HTTP Headers</A></H1></CENTER>
+<P>
+When writing your own handlers with Perl API the proper way to send the
+HTTP Header is to set the header first and then to send it. Like:
+
+<P>
+<PRE> $r->content_type('text/html');
+ $r->send_http_header;
+ return OK if $r->header_only;
+</PRE>
+<P>
+If the client issues a HTTP <CODE>HEAD</CODE> request rather than the usual
+<CODE>GET</CODE>, to be compilent with the HTTP protocol we better will not send the
+document body, but the the HTTP header only. When Apache receives a HEAD
+request, it sets <EM>header_only()</EM> to true. If we see that this has happened, we return from the handler
+immediately with an OK status code.
+
+<P>
+Generally, you don't need the explicit content type setting, since Apache
+does it for you, by looking up the MIME type of the request by matching the
+extension of the URI in the MIME tables (from the
+<CODE>mime.types</CODE> file). So if the request URI is <CODE>/welcome.html</CODE>, the
+<CODE>text/html</CODE> content-type will be picked. However for CGI scripts or URIs that cannot be
+mapped by a known extension, you should set the appropriate type by using <CODE>content_type()</CODE> method.
+
+<P>
+The situation is a little bit different with <CODE>Apache::Registry</CODE> and alike handlers. It means that if you take a basic CGI script like:
+
+<P>
+<PRE> print "Content-type: text/plain\n\n";
+ print "Hello world";
+</PRE>
+<P>
+it wouldn't work, because the HTTP header will be not sent. By default,
+mod_perl does not send any headers by itself, however, you may wish to
+change this by adding:
+
+<P>
+<PRE> PerlSendHeader On
+</PRE>
+<P>
+in <CODE><Location</CODE>> part of your configuration. Now the response line and common headers
+will be sent as they are by mod_cgi. And, just as with mod_cgi, <CODE>PerlSendHeader</CODE> will not send the MIME type and a terminating double newline. Your script
+must send that itself, e.g.:
+
+<P>
+<PRE> print "Content-type: text/html\r\n\r\n";
+</PRE>
+<P>
+Note, that the book always uses ``\n\n'' and not ``\r\n\r\n''. The latter
+is a way to send new lines as defined in HTTP standards, but as of this
+moment all the browsers accept the former format as well. To follow
+strictly the HTTP protocol you must you the ``\r\n'' format.
+
+<P>
+The <STRONG>PerlSendHeader On</STRONG> directive tells mod_perl to intercept anything that looks like a header
+line (such as <CODE>Content-Type:
+text/plain</CODE>) and automatically turn it into a correctly formatted HTTP/1.0 header, the
+same way it happens with CGI scripts running under mod_cgi. This allows you
+to keep your CGI scripts unmodified.
+
+<P>
+There is <CODE>$ENV{PERL_SEND_HEADER}</CODE> which tells whether
+<CODE>PerlSendHeader</CODE> is <CODE>On</CODE> or <CODE>Off</CODE>. You can use it in your module like:
+
+<P>
+<PRE> if($ENV{PERL_SEND_HEADER}) {
+ print "Content-type: text/html\n\n";
+ }
+ else {
+ my $r = Apache->request;
+ $r->content_type('text/html');
+ $r->send_http_header;
+ }
+</PRE>
+<P>
+If you use <EM>CGI.pm</EM>'s <EM>header()</EM> function to generate HTTP headers, you do not need to activate this
+directive because <EM>CGI.pm</EM> detects
+<EM>mod_perl</EM> and calls <EM>send_http_header()</EM> for you. However, it does not hurt to use this directive anyway.
+
+<P>
+There is no free lunch -- you get the mod_cgi behavior on cost of little
+but still overhead of parsing the text that is being sent, and mod_perl
+makes the assumption that individual headers are not split across print
+statements.
+
<P>
-You can accomplish this in two ways - in the <CODE>Apache::Registry</CODE> script:
+The <CODE>Apache::print()</CODE> routine has to gather up the headers that your script outputs, in order to
+pass them to <CODE>$r-&gt;send_http_header</CODE>. This happens in <CODE>src/modules/perl/Apache.xs</CODE> (<CODE>print</CODE>) and
+<CODE>Apache/Apache.pm</CODE> (<CODE>send_cgi_header</CODE>). There is a shortcut in there, namely the assumption that each print
+statement contains one or more complete headers. If for example you used to
+generate a
+<CODE>Set-Cookie</CODE> header by multiply <CODE>print()</CODE> statements, like:
<P>
-<PRE> Apache->request->child_terminate;
+<PRE> print "Content-type: text/html\n";
+ print "Set-Cookie: iscookietext\; ";
+ print "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
+ print "path=\/\; ";
+ print "domain=\.mmyserver.com\; ";
+ print "\n\n";
+ print "hello";
</PRE>
<P>
-in httpd.conf:
+your generated <CODE>Set-Cookie</CODE> header is split over a number of print statements and gets lost. The above
+example wouldn't work! Try this instead:
<P>
-<PRE> PerlFixupHandler "sub { shift->child_terminate }"
+<PRE> print "Content-type: text/html\n";
+ my $cookie = "Set-Cookie: iscookietext\; ";
+ $cookie .= "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
+ $cookie .= "path=\/\; ";
+ $cookie .= "domain=\.mmyserver.com\; ";
+ print $cookie;
+ print "\n\n";
+ print "hello";
</PRE>
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Running_from_shell">Running from shell</A></H2></CENTER>
<P>
-Your scripts <STRONG>will not</STRONG> run from the command line (yet) unless you use <CODE>CGI::Switch</CODE> or <CODE>CGI.pm</CODE> and perl 5.004+ and do not make any direct calls to <CODE>Apache-&gt;methods</CODE>.
+Sometimes when you call a script you see an ugly <CODE>"Content-Type:
+text/html"</CODE> displayed at the top of the page, and of course the HTML code becomes
+broken. As you understand from the above discussion this generally happens
+when your code already send the header, that's why you see it rendered into
+a browser's page. This might happen when you call the <CODE>CGI.pm</CODE> <CODE>$q-&gt;header</CODE> method or mod_perl's
+<CODE>$r-&gt;send_http_header</CODE>.
+
+<P>
+If you have a complicated application where the header might be generated
+from many different places, depending on the calling logic, you might want
+to write a special subroutine that sends a header, and keeps a track
+whether the header has been already sent. Of course you can use a global
+variable to flag that the header has been already sent, but there is
+another elegant solution, where the closure effect is a desired feature.
+
+<P>
+Just copy the code below, including the block's curly braces. And
+everywhere in your code you print the header use the <CODE>print_header()</CODE>
+subroutine. <CODE>$need_header</CODE> is the same kind of beast as a static variable in C, so it remembers its
+value from call to call. The first time you will call the <CODE>print_header</CODE>, the value of <CODE>$need_header</CODE>
+will become zero and on the subsequent calls if any happens, the header
+will be not sent any more.
<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="I_O_is_different">I/O is different</A></H2></CENTER>
+<PRE> {
+ my $need_header = 1;
+ sub print_header {
+ my type = shift || "text/html";
+ print("Content-type: $type\n\n),$need_header = 0 if $need_header;
+ }
+ }
+</PRE>
<P>
-If you are using Perl 5.004 or better, most CGI scripts can run under
-mod_perl untouched. If you're using 5.003, Perl's built-in <CODE>read()</CODE>
-and <CODE>print()</CODE> functions do not work as they do under CGI. If you're using <CODE>CGI.pm</CODE>, use <CODE>$query-&gt;print</CODE> instead of plain 'ol
-<CODE>print()</CODE>.
+In your code you call the above subroutine as:
<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A></H2></CENTER>
+<PRE> print_header();
+</PRE>
<P>
-By default, mod_perl does not send any headers by itself, however, you may
-wish to change this (in <CODE>httpd.conf</CODE>):
+or
<P>
-<PRE> PerlSendHeader On
+<PRE> print_header("text/plain);
</PRE>
<P>
-Now the response line and common headers will be sent as they are by
-mod_cgi. And, just as with mod_cgi, <CODE>PerlSendHeader</CODE> will not send the MIME type and a terminating newline. Your script must
-send that itself, e.g.:
+if you want to override the default (text/html) MIME type.
<P>
-<PRE> print "Content-type: text/html\r\n\r\n";
+Let's make our smart method to elaborate with PerlSendHeader directive
+settings, to always do the right thing. It's especially important if you
+write an application that you are going to distribute, hopefully as an Open
+Source.
+
+<P>
+<PRE> {
+ my $need_header = 1;
+ sub print_header {
+ my type = shift || "text/html";
+ return unless $need_header;
+ $need_header = 0;
+ if($ENV{PERL_SEND_HEADER}) {
+ print "Content-type: $type\n\n";
+ }
+ else {
+ my $r = Apache->request;
+ $r->content_type($type);
+ $r->send_http_header;
+ }
+ }
+ }
</PRE>
<P>
-If you are using <CODE>CGI.pm</CODE> or <CODE>CGI::Switch</CODE> and <STRONG>print
-$q->header</STRONG> you do _not_ need <CODE>PerlSendHeader</CODE> On.
+You can continue to improve this subroutine even further to handle
+additional headers, like cookies and alike.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H2></CENTER>
+<CENTER><H1><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H1></CENTER>
<P>
To run a Non Parsed Header CGI script under mod_perl, simply add to your
code:
@@ -968,8 +2574,7 @@
<PRE> local $| = 1;
</PRE>
<P>
-And if you normally set <CODE>PerlSendHeader On</CODE>, add this to your
-<CODE>httpd.conf</CODE>:
+And if you normally set <CODE>PerlSendHeader On</CODE>, add this to your server's configuration file:
<P>
<PRE> <Files */nph-*>
@@ -978,7 +2583,7 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="BEGIN_blocks">BEGIN blocks</A></H2></CENTER>
+<CENTER><H1><A NAME="BEGIN_blocks">BEGIN blocks</A></H1></CENTER>
<P>
Perl executes <CODE>BEGIN</CODE> blocks during the compile time of code as soon as possible. The same is
true under mod_perl. However, since mod_perl normally only compiles scripts
@@ -1040,7 +2645,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="END_blocks">END blocks</A></H2></CENTER>
+<CENTER><H1><A NAME="END_blocks">END blocks</A></H1></CENTER>
<P>
As perlmod explains, an <CODE>END</CODE> subroutine is executed as late as possible, that is, when the interpreter
exits. In the mod_perl environment, the interpreter does not exit until the
@@ -1063,14 +2668,15 @@
<P>
All other <CODE>END</CODE> blocks encountered during other <CODE>Perl*Handler</CODE>
call-backs, e.g. <CODE>PerlChildInitHandler</CODE>, will be suspended while the process is running and called during <CODE>child_exit()</CODE> when the process is shutting down. Module authors might wish to use
-<CODE>$r-&gt;register_cleanup</CODE> as an alternative to <CODE>END</CODE> blocks if this behavior is not desirable.
+<CODE>$r-&gt;register_cleanup()</CODE> as an alternative to <CODE>END</CODE> blocks if this behavior is not desirable. <CODE>$r-&gt;register_cleanup()</CODE> is being called at the CleanUp processing phase of each request and thus
+can be used to emulate plain perl's <CODE>END{}</CODE> block behavior.
<P>
The last paragraph is very important for the <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Switches_w_T">Switches -w, -T</A></H2></CENTER>
+<CENTER><H1><A NAME="Switches_w_T">Switches -w, -T</A></H1></CENTER>
<P>
Normally when you run perl from the command line or have the shell invoke
it with `#!', you may choose to pass perl switch arguments such as <STRONG>-w</STRONG> or <STRONG>-T</STRONG>. Most command line arguments have a equivalent special variable. For
@@ -1108,7 +2714,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="strict_pragma">strict pragma</A></H2></CENTER>
+<CENTER><H1><A NAME="strict_pragma">strict pragma</A></H1></CENTER>
<P>
It's _absolutely_ mandatory (at least for development) to start all your
scripts with:
@@ -1133,7 +2739,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Turning_warnings_ON">Turning warnings ON</A></H2></CENTER>
+<CENTER><H1><A NAME="Turning_warnings_ON">Turning warnings ON</A></H1></CENTER>
<P>
Have a <CODE>local $^W=1</CODE> in the script or <CODE>PerlWarn ON</CODE> at the server configuration file. Turning the warning on will save you a
lot of troubles with debugging your code. Note that all perl switches, but
@@ -1174,7 +2780,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="diagnostics_pragma">diagnostics pragma</A></H2></CENTER>
+<CENTER><H1><A NAME="diagnostics_pragma">diagnostics pragma</A></H1></CENTER>
<P>
This is a Perl compiler pragma which forces verbose warning diagnostics.
Put at the start of your scripts:
@@ -1197,7 +2803,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A></H2></CENTER>
+<CENTER><H1><A NAME="Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A></H1></CENTER>
<P>
To pass an environment variable from a configuration file, add to it:
@@ -1225,7 +2831,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Global_Variables">Global Variables</A></H2></CENTER>
+<CENTER><H1><A NAME="Global_Variables">Global Variables</A></H1></CENTER>
<P>
It's always a good idea to stay away from global variables when possible.
Some variables must be global so Perl can see them, such as a module's <CODE>@ISA</CODE> or <CODE>$VERSION</CODE> variables (or fully qualified
@@ -1257,13 +2863,13 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A></H2></CENTER>
+<CENTER><H1><A NAME="Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A></H1></CENTER>
<P>
Files pulled in via <STRONG>use</STRONG> or <STRONG>require</STRONG> statements are not automatically reloaded when changed on disk. See <A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A> for more info.
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Apache_and_syslog">Apache and syslog</A></H2></CENTER>
+<CENTER><H1><A NAME="Apache_and_syslog">Apache and syslog</A></H1></CENTER>
<P>
When native syslog support is enabled, the stderr stream will be redirected
to <CODE>/dev/null</CODE>!
@@ -1274,7 +2880,7 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Memory_leakage">Memory leakage</A></H2></CENTER>
+<CENTER><H1><A NAME="Memory_leakage">Memory leakage</A></H1></CENTER>
<P>
Scripts under mod_perl can very easily leak memory! Global variables stay
around indefinitely, lexical variables (declared with <CODE>my()</CODE> are destroyed when they go out of scope, provided there are no references
@@ -1560,176 +3166,6 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
-<P>
-When you develop plain CGI scripts, you can just change the code, and rerun
-the CGI from your browser. Since the script isn't cached in memory, the
-next time you call it the server starts up a new perl process, which
-recompiles it from scratch. The effects of any modifications you've applied
-are immediately present.
-
-<P>
-The situation is different with <CODE>Apache::Registry</CODE>, since the whole idea is to get maximum performance from the server. By
-default, the server won't spend the time to check whether any included
-library modules have been changed. It assumes that they weren't, thus
-saving a few milliseconds to <CODE>stat()</CODE> the source file (multiplied by however many modules/libraries you are <CODE>use()</CODE>-ing and/or <CODE>require()</CODE>-ing in your script.) The only check that is being done is whether your
-main script has been changed. So if you have only one script that doesn't
-<CODE>use()</CODE> (or <CODE>require()</CODE>) other perl modules (or packages), there is nothing new about it. If
-however, you are developing a script that includes other modules, the files
-you <CODE>use()</CODE> or <CODE>require()</CODE> aren't being checked whether they have been modified.
-
-<P>
-Acknowledging this, how do we get our modperl-enabled server to recognize
-changes in any library modules? Well, there are a couple of techniques:
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
-<P>
-The simplest approach is to restart the server each time you apply some
-change to your code. See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Using_Apache_StatINC">Using Apache::StatINC</A></H2></CENTER>
-<P>
-After restarting the server about 100 times, you will be tired and will
-look for another solutions. Help comes from the
-<CODE>Apache::StatINC</CODE> module.
-
-<P>
-<CODE>Apache::StatINC</CODE> reloads <CODE>%INC</CODE> files when updated on disk. When Perl pulls a file via require, it stores
-the filename in the global hash <CODE>%INC</CODE>. The next time Perl tries to require the same file, it sees the file in <CODE>%INC</CODE> and does not reload from disk. This module's handler iterates over <CODE>%INC</CODE> and reloads the file if it has changed on disk.
-
-<P>
-To enable this module just add two lines to <CODE>httpd.conf</CODE> file.
-
-<P>
-<PRE> PerlModule Apache::StatINC
- PerlInitHandler Apache::StatINC
-</PRE>
-<P>
-To be sure it really works, turn on the debug mode on your development box
-with <CODE>PerlSetVar StatINCDebug On</CODE>. You end up with something like:
-
-<P>
-<PRE> PerlModule Apache::StatINC
- <Location /perl>
- SetHandler perl-script
- PerlHandler Apache::Registry::handler
- Options ExecCGI
- PerlSendHeader On
- PerlInitHandler Apache::StatINC
- PerlSetVar StatINCDebug On
- </Location>
-</PRE>
-<P>
-Beware that only the modules located in <CODE>@INC</CODE> are being reloaded on change, and you can change the <CODE>@INC</CODE> only before the server has been started (in startup file).
-
-<P>
-Whatever you do in your scripts and modules which are being <CODE>required()</CODE> after the server startup will not have any effect on <CODE>@INC</CODE>. When you do:
-
-<P>
-<PRE> use lib qw(foo/bar);
-</PRE>
-<P>
-the <CODE>@INC</CODE> is being changed only for the time the code is being parsed and compiled.
-When it's over the <CODE>@INC</CODE> is being reset to its original value. To make sure that you have set a
-correct <CODE>@INC</CODE> fetch <A
-HREF="http://www.nowhere.com/perl-status?inc">http://www.nowhere.com/perl-status?inc</A>
-and look at the bottom of the page. (I assume you have configured the <A HREF="././config.html#_perl_status_location">/perl-status location</A>.)
-
-<P>
-Also, notice the following caveat: While ``<CODE>.</CODE>'' is in the <CODE>@INC</CODE> -- perl knows to <CODE>require()</CODE> files relative to the script directory. Once the script was parsed - the
-server doesn't remember the path any more! So you end up with broken entry
-in <CODE>%INC</CODE> like:
-
-<P>
-<PRE> $INC{bar.pl} eq "bar.pl"
-</PRE>
-<P>
-If you want Apache::StatINC to reload your script - modify the <CODE>@INC</CODE>
-at the server startup file! or use a full path in <CODE>require()</CODE> call.
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Reloading_only_specific_files">Reloading only specific files</A></H2></CENTER>
-<P>
-Checking all the modules in <STRONG>%INC</STRONG> every time can add a large overhead to server response times, and you
-certainly would not want
-<CODE>Apache::StatINC</CODE> module to be enabled in your production site's configuration. But sometimes
-you want to have some Configuration module to be reloaded without
-restarting the whole server. To accomplish this, one of the solutions is to
-use a code that I describe below.
-
-<P>
-Assuming that you start your script with loading <CODE>Foo::Bar</CODE> and importing some tags:
-
-<P>
-<PRE> use lib "/some/private/path";
- use Foo::Bar qw(:tags_group tag1 tag2);
-</PRE>
-<P>
-Now to make a modification testing and reload at runtime you have to use
-something like this:
-
-<P>
-<PRE> # child's private global variable to keep the timestamps
- use vars qw(%MODIFIED);
-
- my $module = "Foo::Bar";
-
- (my $inc_key = $module) =~ s|::|/|g;
- $inc_key .= ".pm";
- # the $module's path should be registered in %INC if it was already loaded
- my $path = $INC{$inc_key} or warn "Can't find $inc_key in %INC\n";
-
- # Note: consider to not continue if $path wasn't set!
-
- # set modification time if it wasn't set before (first time)
- # Note: Use (stat $path)[9] instead of -M test, if you reset
- # time with $^M=time
- $MODIFIED{$module} ||= -M $path;
-
- # now check whether it was changed (assuming the above wasn't
- # performed in this session
- if ($MODIFIED{$module} != -M $path){
- # only if deleted from %INC the require will be called below
- delete $INC{$inc_key};
-
- require $path;
-
- # now reimport the symbols (if you need them back :)
- import $module qw(:tags_group tag1 tag2);
-
- # Update the MODIFICATION times
- $MODIFIED{$module} = -M $path;
- }
-</PRE>
-<P>
-You may want to add debug print statements to debug this code in your
-application.
-
-<P>
-Read the ``use versus require'' article for more info. ( <A
-HREF="http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require">http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require</A>
-)
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Reloading_handlers">Reloading handlers</A></H2></CENTER>
-<P>
-If you want to reload perlhandler on each invocation, the following trick
-will do it:
-
-<P>
-<PRE> PerlHandler "sub { do 'MyTest.pm'; MyTest::handler(shift) }"
-</PRE>
-<P>
-<CODE>do()</CODE> will reload <CODE>MyTest.pm</CODE> every request.
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A></H1></CENTER>
<P>
When you write a script running under mod_cgi, you can get away with sloppy
@@ -1894,6 +3330,40 @@
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Sharing_variables_between_proces">Sharing variables between processes</A></H1></CENTER>
+<P>
+META: to be completed
+
+<UL>
+<P><LI>
+<P>
+Global variables initialized at the server startup, through the Perl
+startup file, can be shared between processes, untill modified by some of
+the processes. e.g. when you write:
+
+<P>
+<PRE> $My::debug = 1;
+</PRE>
+<P>
+all processes will read the same value. If one of the processes changes
+that value to <CODE>0</CODE>, it'll be still equal to <CODE>1</CODE> for any process, but the one who actually did the change. When the process
+modifies the variable, it becomes process' private copy.
+
+<P><LI>
+<P>
+<CODE>IPC::Shareable</CODE> can be used to share variables between children.
+
+<P><LI>
+<P>
+libmm
+
+<P><LI>
+<P>
+other methods?
+
+</UL>
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A></H1></CENTER>
<P>
To trap all/most Perl run-time errors and send the output to the client
@@ -2099,23 +3569,27 @@
</PRE>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A></H1></CENTER>
+<CENTER><H1><A NAME="Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A></H1></CENTER>
<P>
Generally you should not fork from your mod_perl scripts, since when you do
-- you are forking the entire apache web server, lock, stock and barrel.
Not only is your perl code being duplicated, but so is mod_ssl,
mod_rewrite, mod_log, mod_proxy, mod_spelling or whatever modules you have
-used in your server, all the core routines and so on. A much wiser approach
-would be to spawn a sub-process, hand it the information it needs to do the
-task, and have it detach (close x3 +
+used in your server, all the core routines and so on.
+
+<P>
+A much wiser approach would be to spawn a sub-process, hand it the
+information it needs to do the task, and have it detach (close x3 +
<CODE>setsid()</CODE>). This is wise only if the parent who spawns this process, immediately
-continue, you do not wait for the sub process to complete. This approach is
+continue, you do not wait for the sub-process to complete. This approach is
suitable for a situation when you want to trigger a long time taking
process through the web interface, like processing some data, sending email
to thousands of subscribed users and etc. Otherwise, you should convert the
code into a module, and use its functions or methods to call from CGI
-script. Just making a
-<CODE>system()</CODE> call defeats the whole idea behind mod_perl, perl interpreter and modules
+script.
+
+<P>
+Just making a <CODE>system()</CODE> call defeats the whole idea behind mod_perl, perl interpreter and modules
should be loaded again for this external program to run.
<P>
@@ -2156,55 +3630,97 @@
post-processing, look into <CODE>PerlCleanupHandler</CODE>.
<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A></H1></CENTER>
+If you are interested in more deep level details, this is what actually
+happens when you fork and make a system call, like
+
<P>
-The <CODE>Apache::print()</CODE> routine has to gather up the headers that your script outputs, in order to
-pass them to <CODE>$r-&gt;send_http_header</CODE>. This happens in <CODE>src/modules/perl/Apache.xs</CODE> (<CODE>print</CODE>) and
-<CODE>Apache/Apache.pm</CODE> (<CODE>send_cgi_header</CODE>). There is a shortcut in there, namely the assumption that each print
-statement contains one or more complete headers. If for example you used to
-generate a
-<CODE>Set-Cookie</CODE> header by multiply <CODE>print()</CODE> statements, like:
+<PRE> system("echo Hi"),exit unless fork();
+</PRE>
+<P>
+What happens is that <CODE>fork()</CODE> gives you 2 execution paths and
+the child gets virtual memory sharing a copy of the program text (read
+only) and sharing a copy of the data space copy-on-write (remember why you
+pre-load modules in mod_perl?). In the above code a parent will immediately
+continue with the code that comes up after the fork, while the forked
+process will execute <CODE>system("echo Hi")</CODE> and then terminate itself. Note that you might need to set:
<P>
-<PRE> print "Content-type: text/html\n";
- print "Set-Cookie: iscookietext\; ";
- print "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
- print "path=\/\; ";
- print "domain=\.mmyserver.com\; ";
- print "\n\n";
- print "hello";
+<PRE> $SIG{CHLD} = sub {wait};
</PRE>
<P>
-your generated <CODE>Set-Cookie</CODE> header is split over a number of print statements and gets lost. Try this:
+or
<P>
-<PRE> print "Content-type: text/html\n";
- my $cookie = "Set-Cookie: iscookietext\; ";
- $cookie .= "expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; ";
- $cookie .= "path=\/\; ";
- $cookie .= "domain=\.mmyserver.com\; ";
- print $cookie;
- print "\n\n";
- print "hello";
+<PRE> $SIG{CHLD} = IGNORE;
+</PRE>
+<P>
+or the terminated process might become a zombie. Normally, every process
+has its parent, many processes a children of PID 1, the init process.
+Zombie, is a process that doesn't have a father. When the child quits, it
+reports the termination to his parent. If he doesn't know who the father is
+it becomes zombie. (META: Did I formulate it correctly?)
+
+<P>
+The only work is setting up the page tables for the virtual memory and the
+second process goes on its separate way.
+
+<P>
+Next, Perl will find <CODE>/bin/echo</CODE> along the search path, and invoke it directly. Perl <CODE>system()</CODE>
+is *not* <CODE>system(3)</CODE> [C-library]. Only when the command has shell meta-chars does Perl invoke a
+real shell. That's a *very* nice optimization.
+
+<P>
+Only if you do:
+
+<P>
+<PRE> system "sh -c 'echo foo'"
</PRE>
<P>
-<META> some leftovers... # =head1 Coding with mod_perl
+OS actually parses your command with a shell so you <CODE>exec()</CODE> a
+copy of
+<CODE>/bin/sh</CODE>, but since one is almost certainly already running somewhere, the system
+will notice that (via the disk inode reference) and replace your virtual
+memory page table with one pointed at the already-loaded program code plus
+your own data space. Then the shell parses the passed command.
<P>
-Before you start coding for <CODE>Apache::Registry</CODE>, you have to change your programming state of mind. Scripts running under
-mod_perl are like subroutines are being called from a continually running
-daemon. Imagine a daemon process that when requested to process some
-script, reads it in, compiles it as a subroutine, and finally executes it.
-On any subsequent request, it'll just recall the already compiled
-subroutine. Hope that you get the idea.
+Since it is <CODE>echo</CODE>, it will execute it as a built-in in the latter example or a <CODE>/bin/echo</CODE> in the former and be done, but this is only an example. You aren't calling <CODE>system("echo Hi")</CODE> in your mod_perl scripts, right? Since most other real things (heavy
+programs executed as a subprocess) would involve repeating the process to
+load the specified command or script (it might involve some actual demand
+paging from the program file if you execute new code).
<P>
-The best thing you do when coding from scratch is to make it clean and use
-packages. By ``make it clean'' we mean make certain that you <STRONG>use
-strict;</STRONG> and that your script produces no warnings when tested via
-<STRONG>perl -cw myscript.pl</STRONG>. As you go thru the notes you will understand why. </META>
+The only place you see real overhead from this scheme is when the parent
+process is huge (unfortunately like mod_perl...) and the page table becomes
+large as a side effect. The whole point of mod_perl is to avoid having to
+<CODE>fork()</CODE> / <CODE>exec()</CODE> something on every hit, though.
+Perl can do just about anything by itself. However, you probably won't get
+in trouble until you hit about 30 forks/sec on a so-so pentium.
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A></H1></CENTER>
+<P>
+Let's say that you wrote a few handlers to process a request, and they all
+need to share some custom Perl data structure. The <CODE>pnotes()</CODE>
+method comes to rescue. Taken that one of the handlers stored some data in
+hash <CODE>%my_data</CODE>, before it finished its activity:
+
+<P>
+<PRE> # First handler:
+ $r->pnotes('my_info' => \%hash);
+</PRE>
+<P>
+All the following handler will be able to retrive the stored data with.
+
+<P>
+<PRE> # Later handler:
+ my $info = $r->pnotes('my_info');
+ print $info->{foo};
+</PRE>
+<P>
+The stored information will be destroyed at the end of the request.
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
@@ -2215,6 +3731,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="start.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -2228,7 +3754,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/17/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
1.18 +34 -3 modperl-site/guide/scenario.html
Index: scenario.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/scenario.html,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- scenario.html 1999/08/17 19:03:45 1.17
+++ scenario.html 1999/09/25 23:14:16 1.18
@@ -73,6 +73,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A></H1></CENTER>
@@ -92,7 +101,7 @@
% perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
DO_HTTPD=1 USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
% make && make test && make install
- % cd ../apache_x.x.x/src
+ % cd ../apache_x.x.x
% make install
</PRE>
<P>
@@ -163,7 +172,7 @@
directory tree and to put the <CODE>httpd</CODE> there.
<P>
-<PRE> % cd ../apache_x.x.x/src
+<PRE> % cd ../apache_x.x.x
% make install
</PRE>
<P>
@@ -1230,6 +1239,14 @@
coming from, before changing the <CODE>remote_ip</CODE>.
<P>
+Generally you shouldn't trust the <CODE>X-Forwarded-For</CODE> header. You only want to rely on <CODE>X-Forwarded-For</CODE> headers from proxies you control yourself. If you know how to spoof a
+cookie you've probably got the general idea on making HTTP headers and can
+spoof the
+<CODE>X-Forwarded-For</CODE> header as well. The only address *you* can count on as being a reliable
+value is the one from
+<CODE>r-&gt;connection-&gt;remote_ip</CODE>.
+
+<P>
From that point on, the remote IP address is correct. You should be able to
access <CODE>REMOTE_ADDR</CODE> as usual.
@@ -1281,6 +1298,10 @@
The only possible caveat in the config file is that your <CODE>Auth</CODE> stuff needs to be in <CODE><Directory ...</CODE>> ... <CODE></Directory</CODE>> tags because if you use a <CODE><Location /...</CODE>> ... <CODE></Location</CODE>> the proxypass server takes the auth info for its own authentication
and would not pass it on.
+<P>
+The same with mod_ssl, if plugged into a front-end server, all the SSL
+requests be encoded/decoded properly by it.
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
@@ -1291,6 +1312,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="strategy.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="install.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -1304,7 +1335,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/17/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
1.6 +80 -5 modperl-site/guide/security.html
Index: security.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/security.html,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- security.html 1999/08/17 19:03:45 1.5
+++ security.html 1999/09/25 23:14:17 1.6
@@ -36,7 +36,8 @@
<LI><A HREF="#Authentication_code_snippets">Authentication code snippets</A>
<UL>
- <LI><A HREF="#Forcing_reauthenticating">Forcing reauthenticating</A>
+ <LI><A HREF="#Forcing_re_authentication">Forcing re-authentication</A>
+ <LI><A HREF="#OK_AUTH_REQUIRED_and_FORBIDDEN_">OK, AUTH_REQUIRED.and FORBIDDEN in Authentication handlers</A>
</UL>
</UL>
@@ -54,6 +55,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="An_Importance_of_Your_site_s_Sec">An Importance of Your site's Security</A></H1></CENTER>
@@ -228,22 +238,77 @@
<CENTER><H1><A NAME="Authentication_code_snippets">Authentication code snippets</A></H1></CENTER>
<P>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H2><A NAME="Forcing_reauthenticating">Forcing reauthenticating</A></H2></CENTER>
+<CENTER><H2><A NAME="Forcing_re_authentication">Forcing re-authentication</A></H2></CENTER>
<P>
To force authenticated user to reauthenticate just send the following
header to the browser:
<P>
-<PRE> HTTP/1.0 401 Unauthorized
+<PRE> WWW-Authenticate: Basic realm="My Realm"
+ HTTP/1.0 401 Unauthorized
</PRE>
<P>
-This will pop-up (on Netscape at least) a window saying that the
+This will pop-up (in Netscape at least) a window saying that the
<STRONG>Authorization Failed. Retry?</STRONG> And an <STRONG>OK</STRONG> and a <STRONG>Cancel</STRONG> buttons. When that window pops up you know that the password has been
cleared. If the user hits the <STRONG>Cancel</STRONG> button the username will also be cleared, and you can have a page that will
be output written after the header if this is a CGI (or PHP, or anything
else like that). If the user hits the <STRONG>OK</STRONG> button, the authentication window will be brought up again with their
previous username already in the username field.
+<P>
+In Perl API you would use <CODE>note_basic_auth_failure()</CODE> method to
+force reauthentication.
+
+<P>
+Since the browser's behaviour is in no way guaranteed, it also may not
+work, and that should be noted.
+
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H2><A NAME="OK_AUTH_REQUIRED_and_FORBIDDEN_">OK, AUTH_REQUIRED.and FORBIDDEN in Authentication handlers</A></H2></CENTER>
+<P>
+When your authentication handler returns OK, it means that user has
+correctly authenticated and now <CODE>$r-&gt;connection-&gt;user</CODE> will have the username set for all the subsequent requests. For
+<CODE>Apache::Registry</CODE> and friends, where the environment variables setting weren't turned off, an
+equivalent <CODE>$ENV{REMOTE_USER}</CODE>
+variable will be available. Password is available only through Perl API
+with help of <CODE>get_basic_auth_pw()</CODE> method.
+
+<P>
+If there is a failure, returned <CODE>AUTH_REQUIRED</CODE> flag will tell the browser to pop up an authentication window, to try
+again, unless it's a first time. For example:
+
+<P>
+<PRE> my($status, $sent_pw) = $r->get_basic_auth_pw;
+ unless($r->connection->user and $sent_pw) {
+ $r->note_basic_auth_failure;
+ $r->log_reason("Both a username and password must be provided");
+ return AUTH_REQUIRED;
+ }
+</PRE>
+<P>
+Let's say that you have a mod_perl authen handler, where user credentials
+are checked against a database, and it either returns
+<CODE>OK</CODE> or <CODE>AUTH_REQUIRED</CODE>. One of the possible authentication failure case might happen when the
+username/password are correct, but the user's account has been suspended
+temporarily.
+
+<P>
+If this is the case you would like to make the user aware of this, through
+a page display instead of having the browser pop up the auth dialog again.
+At the same time you need to refuse the authentication, of course.
+
+<P>
+The solution is to return <CODE>FORBIDDEN</CODE>, but before that you should set a custom error page for this specific
+handler, with help of
+<CODE>$r-&gt;custom_response</CODE>. Something like:
+
+<P>
+<PRE> use Apache::Constants qw(:common);
+ $r->custom_response(SERVER_ERROR, "/errors/suspended_account.html");
+
+ return FORBIDDEN if $suspended;
+</PRE>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
@@ -254,6 +319,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="warnings.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -267,7 +342,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/29/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
1.16 +19 -42 modperl-site/guide/snippets.html
Index: snippets.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/snippets.html,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- snippets.html 1999/08/17 19:03:45 1.15
+++ snippets.html 1999/09/25 23:14:18 1.16
@@ -26,8 +26,6 @@
<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
<UL>
- <LI><A HREF="#Sending_MIME_headers">Sending MIME headers</A>
- <LI><A HREF="#How_to_avoid_printing_the_header">How to avoid printing the header more than once</A>
<LI><A HREF="#More_on_relative_paths">More on relative paths</A>
<LI><A HREF="#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server</A>
<LI><A HREF="#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
@@ -47,48 +45,17 @@
<HR>
- <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<P>
-<CENTER><H1><A NAME="Sending_MIME_headers">Sending MIME headers</A></H1></CENTER>
-<P>
-By default, mod_perl does not send any headers by itself, however, you may
-wish to change this behavior by setting in the config file:
-
-<P>
-<PRE> PerlSendHeader On
-</PRE>
-<P>
-The safest bet is to use CGI.pm's <CODE>header()</CODE> method. (If you do <CODE>print header();</CODE>, you don't need the above setting.)
-
-<P>
-Also there is <CODE>$ENV{PERL_SEND_HEADER}</CODE> to see if <CODE>PerlSendHeader</CODE> is <CODE>On</CODE> or
-<CODE>Off</CODE>.
-
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
-<CENTER><H1><A NAME="How_to_avoid_printing_the_header">How to avoid printing the header more than once</A></H1></CENTER>
-<P>
-I'm sure you have been in situations where you wish you knew whether the
-MIME header has already been printed. Since if it is printed again it will
-cause an ugly ``Content-type: ...'' string to show up in the browser. So
-how do we solve it? With the help of a closure.
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
-<P>
-Just copy the code below, including the block's curly parentheses. And
-everywhere in your code you print the header use the <CODE>print_header()</CODE> sub.
-<CODE>$need_header</CODE> is the same kind of beast as a static variable in C, so it remembers its
-value from call to call.
+ <HR>
+ <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
-<PRE> {
- my $need_header = 1;
- sub print_header {
- print header(@_),$need_header = 0 if $need_header;
- }
- }
-</PRE>
-<P>
-<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="More_on_relative_paths">More on relative paths</A></H1></CENTER>
<P>
Many people use relative paths for <CODE>require</CODE>, <CODE>use</CODE>, etc., or open files in the current directory or relative to the current
@@ -284,6 +251,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="perl.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -297,7 +274,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 08/17/1999
+ <BR>Last Modified at 09/25/1999
</FONT>
</B>
</TD>
1.17 +35 -7 modperl-site/guide/start.html
Index: start.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/start.html,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- start.html 1999/08/17 19:03:46 1.16
+++ start.html 1999/09/25 23:14:18 1.17
@@ -42,18 +42,26 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="What_s_inside_">What's inside?</A></H1></CENTER>
<P>
-Before you start installing mod_perl, you should have an overall picture of
-this wonderful technology. There is more then one way to use a
+Before you start with mod_perl installation, you should have an overall
+picture of this wonderful technology. There is more then one way to use a
mod_perl-enabled webserver. You have to decide what mod_perl scheme you
-want to use. <A HREF="././strategy.html#">Picking the Right Strategy</A>
-chapter presents various approaches and discusses their pros and cons.
+want to use. <A HREF="././strategy.html#">Picking the Right Strategy</A> chapter presents various approaches and discusses their pros and cons.
<P>
-Once you know what fits your requirements the best, you should proceed to <A HREF="././scenario.html#">Real World Scenarios Implementaion</A>. This chapter provides very detailed scenarios of the schemes discussed in
+Once you know what fits your requirements the best, you should proceed to <A HREF="././scenario.html#">Real World Scenarios Implementation</A>. This chapter provides very detailed scenarios of the schemes discussed in
the
<A HREF="././strategy.html#">Picking the Right Strategy</A> chapter.
@@ -98,6 +106,9 @@
the chapter <A HREF="././warnings.html#">Warnings and Errors: Where and Why</A>.
<P>
+<A HREF="././security.html#">Protecting Your Site</A> - Everything regarding security.
+
+<P>
If you are into driving relational databases with your cgi scripts, the <A HREF="././databases.html#">mod_perl and Relational Databases</A> chapter will tell you all about the database-related goodies mod_perl has
prepared for you.
@@ -110,7 +121,7 @@
possible? Is it secure? Will it work? What resources does it take? The <A HREF="././multiuser.html#">mod_perl for ISPs. mod_perl and Virtual Hosts</A>
chapter answers all these questions. If you want to run a mod_perl- enabled
server, but do not have root access, read this chapter as well, either to
-learn how do it yourself, or maybe to persuade your ISP to provide this
+learn how to do it yourself, or maybe to persuade your ISP to provide this
service.
<P>
@@ -155,6 +166,13 @@
writing the scripts.
<P>
+The <A HREF="././hardware.html#">Choosing an Operating System and Hardware</A> chapter gives you an idea on how to choose the SW and HW for the webserver.
+
+<P>
+The <mod_perl Advocacy|advocacy/> tries to help to make it easier to
+advocate mod_perl around the world.
+
+<P>
The <A HREF="././help.html#">Getting Helped and Further Learning</A> chapter refers you to other related information resources, like learning
Perl programming and SQL, understanding security, building databases, and
more.
@@ -174,6 +192,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="intro.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -187,7 +215,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/29/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>
1.17 +19 -0 modperl-site/guide/status.html
Index: status.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/status.html,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- status.html 1999/08/17 19:03:46 1.16
+++ status.html 1999/09/25 23:14:19 1.17
@@ -49,6 +49,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Watching_the_server">Watching the server</A></H1></CENTER>
@@ -147,6 +156,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="multiuser.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.7 +19 -0 modperl-site/guide/strategy.html
Index: strategy.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/strategy.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- strategy.html 1999/08/17 19:03:46 1.6
+++ strategy.html 1999/09/25 23:14:20 1.7
@@ -49,6 +49,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="Do_it_like_me_">Do it like me?!</A></H1></CENTER>
@@ -683,6 +692,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="performance.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
1.18 +37 -3 modperl-site/guide/warnings.html
Index: warnings.html
===================================================================
RCS file: /export/home/cvs/modperl-site/guide/warnings.html,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- warnings.html 1999/08/17 19:03:46 1.17
+++ warnings.html 1999/09/25 23:14:20 1.18
@@ -45,6 +45,7 @@
<LI><A HREF="#RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A>
<LI><A HREF="#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
<LI><A HREF="#server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A>
+ <LI><A HREF="#syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near "line arguments:"</A>
</UL>
<!-- INDEX END -->
@@ -60,6 +61,15 @@
<HR>
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<P>
<CENTER><H1><A NAME="General_Advice">General Advice</A></H1></CENTER>
@@ -385,8 +395,8 @@
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
<CENTER><H1><A NAME="Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A></H1></CENTER>
<P>
-Not all Perl modules can survive a reload. PerlFreshRestart does not much
-more than:
+Unfortunately, not all perl modules are robust enough to survive reload,
+for them, unusual situation. PerlFreshRestart does not much more than:
<P>
<PRE> while (my($k,$v) = each %INC) {
@@ -408,6 +418,20 @@
<P>
See <A HREF="././performance.html#Choosing_MaxClients">Choosing MaxClients</A>.
+<P>
+<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
+<CENTER><H1><A NAME="syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near "line arguments:"</A></H1></CENTER>
+<P>
+<PRE> syntax error at /dev/null line 1, near "line arguments:"
+ Execution of /dev/null aborted due to compilation errors.
+ parse: Undefined error: 0
+</PRE>
+<P>
+There is a chance that your <CODE>/dev/null</CODE> device is broken. Try:
+
+<P>
+<PRE> % sudo echo > /dev/null
+</PRE>
<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
The <a href="http://www.modperl.com/">
<B>Writing Apache Modules with Perl and C</B></a>
@@ -418,6 +442,16 @@
Amazon.com</a>.
<HR>
+
+ Your corrections of either technical or grammatical
+ errors are very welcome. You are encouraged to help me
+ to improve this guide. If you have something to
+ contribute please <A
+ HREF="help.html#This_document_s_Author"> send it
+ directly to me</A>.
+
+ <HR>
+
[ <A HREF="obvious.html">Prev</A> | <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A> ]
<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
@@ -431,7 +465,7 @@
<B>
<FONT SIZE=-1>
Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
- <BR>Last Modified at 07/09/1999
+ <BR>Last Modified at 09/26/1999
</FONT>
</B>
</TD>