I've finally had time to dig deeper in the troubling $0 and process display problems that seem to exist at least on *BSDs and HP-UX.
On linux, modifications to the original argv[0] will directy modify the process
information. On some other OSes, some special API is needed.
Perl's $0 magic handling correctly handles these OS differences and just does
the right thing.
So, simply passing Perl a _copy_ of argv[0] does disable $0 magic on Linux, but
not on the other OSes where it just calls the correct API (setproctitle() on
BSDs)
On top of that, calling perl_parse() as is commonly done for embedders with
an argument of -e0, results in an initial $0 of '-e'. And that's what
is hapenning to pradeep.
But that's not all ;-) ap_server_argv0 _is_ _not_ httpd' argv[0], it's argv[0]
skipped forward to remove path components and leave only the binary's name
(httpd). The correct way to get at the real argv[0] is in server->proc->argv
All this combined has led to a more than troubling bug.
The correct solution (see patch) is:
- Reset $0 to the _real_ argv[0] after calling perl_parse()
/* Also need to fix PL_origalen */
PL_origalen = strlen(argv[0])+1;
/* argv[0] = '/usr/bin/httpd' */
sv_setpv_mg(get_sv("0",0), argv[0]);
- Use the real argv[0] (s->process->argv) and not a copy
--
Philippe M. Chiasson m/gozer\@(apache|cpan|ectoplasm)\.org/ GPG KeyID : 88C3A5A5
http://gozer.ectoplasm.org/ F9BF E0C2 480E 7680 1AE5 3631 CB32 A107 88C3A5A5
Index: src/modules/perl/modperl_module.c
===================================================================
--- src/modules/perl/modperl_module.c (revision 290798)
+++ src/modules/perl/modperl_module.c (working copy)
@@ -387,7 +387,7 @@
* needed by the Perl callback.
*/
if (!scfg) {
- scfg = modperl_config_srv_new(p);
+ scfg = modperl_config_srv_new(p, s);
modperl_set_module_config(s->module_config, scfg);
scfg->server = s;
}
Index: src/modules/perl/mod_perl.c
===================================================================
--- src/modules/perl/mod_perl.c (revision 290798)
+++ src/modules/perl/mod_perl.c (working copy)
@@ -271,6 +271,13 @@
PL_reentrant_buffer->_crypt_struct.current_saltbits = 0;
#endif
+ /* We need to reset $0 to argv[0] (httpd) since perl_parse() will
+ * have set it to '-e'. Being magic-aware ensures that some
+ * OS-specific magic will happen (i.e. setproctitle() on *BSDs)
+ */
+ PL_origalen = strlen(argv[0]) + 1;
+ sv_setpv_mg(get_sv("0",0), argv[0]);
+
perl_run(perl);
#ifdef USE_ITHREADS
Index: src/modules/perl/modperl_config.c
===================================================================
--- src/modules/perl/modperl_config.c (revision 290798)
+++ src/modules/perl/modperl_config.c (working copy)
@@ -147,7 +147,7 @@
return rcfg;
}
-modperl_config_srv_t *modperl_config_srv_new(apr_pool_t *p)
+modperl_config_srv_t *modperl_config_srv_new(apr_pool_t *p, server_rec *s)
{
modperl_config_srv_t *scfg = (modperl_config_srv_t *)
apr_pcalloc(p, sizeof(*scfg));
@@ -173,18 +173,9 @@
scfg->gtop = modperl_gtop_new(p);
#endif
- /* must copy ap_server_argv0, because otherwise any read/write of
- * $0 corrupts process' argv[0] (visible with 'ps -ef' on most
- * unices). This is due to the logic of calculating PL_origalen in
- * perl_parse, which is later used in set_mg.c:Perl_magic_set() to
- * truncate the argv[0] setting. remember that argv[0] passed to
- * perl_parse() != process's real argv[0].
- *
- * as a copying side-effect, changing $0 now doesn't affect the
- * way the process is seen from the outside.
- */
- modperl_config_srv_argv_push(apr_pstrmemdup(p, ap_server_argv0,
- strlen(ap_server_argv0)));
+ /* make sure httpd's argv[0] is the first argument so $0 is
+ * correctly connected to the real thing */
+ modperl_config_srv_argv_push(s->process->argv[0]);
MP_TRACE_d(MP_FUNC, "new scfg: 0x%lx\n", (unsigned long)scfg);
@@ -233,7 +224,7 @@
void *modperl_config_srv_create(apr_pool_t *p, server_rec *s)
{
- modperl_config_srv_t *scfg = modperl_config_srv_new(p);
+ modperl_config_srv_t *scfg = modperl_config_srv_new(p, s);
if (!s->is_virtual) {
@@ -282,7 +273,7 @@
modperl_config_srv_t
*base = (modperl_config_srv_t *)basev,
*add = (modperl_config_srv_t *)addv,
- *mrg = modperl_config_srv_new(p);
+ *mrg = modperl_config_srv_new(p, add->server);
MP_TRACE_d(MP_FUNC, "basev==0x%lx, addv==0x%lx, mrg==0x%lx\n",
(unsigned long)basev, (unsigned long)addv,
Index: src/modules/perl/modperl_config.h
===================================================================
--- src/modules/perl/modperl_config.h (revision 290798)
+++ src/modules/perl/modperl_config.h (working copy)
@@ -20,7 +20,7 @@
void *modperl_config_dir_merge(apr_pool_t *p, void *basev, void *addv);
-modperl_config_srv_t *modperl_config_srv_new(apr_pool_t *p);
+modperl_config_srv_t *modperl_config_srv_new(apr_pool_t *p, server_rec *s);
modperl_config_dir_t *modperl_config_dir_new(apr_pool_t *p);
Index: t/response/TestDirective/perldo.pm
===================================================================
--- t/response/TestDirective/perldo.pm (revision 290798)
+++ t/response/TestDirective/perldo.pm (working copy)
@@ -11,7 +11,7 @@
sub handler {
my $r = shift;
- plan $r, tests => 15;
+ plan $r, tests => 16;
ok t_cmp('yes', $TestDirective::perl::worked);
@@ -39,7 +39,8 @@
# 3 would mean we are still counting lines from the context of the eval
ok $TestDirective::perl::line > 3;
- ok t_cmp($0, "-e", '$0');
+ ok !t_cmp($0, '-e', '$0');
+ ok t_cmp($0, qr/httpd/, '$0');
ok t_cmp($TestDirective::perl::Included, 1, "Include");
Index: Changes
===================================================================
--- Changes (revision 290798)
+++ Changes (working copy)
@@ -12,6 +12,10 @@
=item 2.0.2-dev
+$0 Fixes : [Gozer]
+- Setting $0 works on Linux again
+- HP-UX and *BSDes show the correct process name instead of '-e'
+
Add the output of ldd(unix/cygwin) and otool -L (darwin)
for httpd to the mp2bug report script.
[Philip M. Gollucci]
signature.asc
Description: OpenPGP digital signature
