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