Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PERL_SYS_INIT()

34 views
Skip to first unread message

Hallvard B Furuseth

unread,
Oct 31, 2011, 9:41:57 AM10/31/11
to
Is PERL_SYS_INIT() as portable as PERL_SYS_INIT3()? It is not
documented in the manpages. I'm wondering if I should use that or
pass a pointer to the possibly less portable extern char **environ;
since proto.h says __attribute__nonnull__ for env.

I'm looking at a program doing roughly

char *embedding[] = { "", "-e", "0" }, **argv = embedding;
int argc = 3;
PERL_SYS_INIT3(&argc, &argv, (char ***)NULL);
...
perl_parse(my_perl, xs_init, 3, argv, NULL);

Can PERL_SYS_INIT(,&argv) change argv? If so, how, and should
the remaining program pass the unchanged 'embedding' or the
changed 'argv' to perl_parse()? man perlembed shows both variants.

--
Hallvard

Ben Morrow

unread,
Oct 31, 2011, 11:46:16 AM10/31/11
to

Quoth Hallvard B Furuseth <h.b.fu...@usit.uio.no>:
> Is PERL_SYS_INIT() as portable as PERL_SYS_INIT3()? It is not
> documented in the manpages. I'm wondering if I should use that or
> pass a pointer to the possibly less portable extern char **environ;
> since proto.h says __attribute__nonnull__ for env.

AFAICT they are only different on OS/2, but _INIT3 was introduced in
5.6, so you should probably use it anyway. (They probably *ought* to be
different at least on Win32, as well, since the Win32 init code affects
the environment, but currently they aren't.)

> I'm looking at a program doing roughly
>
> char *embedding[] = { "", "-e", "0" }, **argv = embedding;
> int argc = 3;
> PERL_SYS_INIT3(&argc, &argv, (char ***)NULL);
> ...
> perl_parse(my_perl, xs_init, 3, argv, NULL);
>
> Can PERL_SYS_INIT(,&argv) change argv? If so, how, and should
> the remaining program pass the unchanged 'embedding' or the
> changed 'argv' to perl_parse()? man perlembed shows both variants.

Perl embedding is not very well tested. There are some notable cases
that work well, like mod_perl, but they all end up knowing more about
the perl guts than is documented in perlembed. About the only way to be
safe is to look at perlmain.c and do what that does, though even that
isn't always possible since it uses symbols that aren't exported on all
platforms. From my experiments with it all I can recommend is to try
things until you find something that works, and to expect to have to make
minor fixes if you upgrade to a new major version of perl.

That said, I believe the correct answer is you should pass the real
environment to _INIT3 (whether from the third arg of main or from the
global environ), and you should pass the argv pointer you passed to
_INIT3 to perl_parse. On some systems (VMS, OS/2) _INIT3 will modify the
passed-in argv; on some systems (Win32, at least) it will modify the
global environment and assume this will affect what perl_parse sees
(ignoring the env pointer passed to _INIT3).

Ben

Hallvard B Furuseth

unread,
Oct 31, 2011, 2:34:37 PM10/31/11
to
Ben Morrow <b...@morrow.me.uk> writes:

> Quoth Hallvard B Furuseth <h.b.fu...@usit.uio.no>:
>> Is PERL_SYS_INIT() as portable as PERL_SYS_INIT3()? It is not
>> documented in the manpages. I'm wondering if I should use that or
>> pass a pointer to the possibly less portable extern char **environ;
>> since proto.h says __attribute__nonnull__ for env.
>
> AFAICT they are only different on OS/2, but _INIT3 was introduced in
> 5.6, so you should probably use it anyway. (They probably *ought* to be
> different at least on Win32, as well, since the Win32 init code affects
> the environment, but currently they aren't.)

Sounds like it's safest to use INIT when available and INIT3 otherwise,
then. That leaves as much as possible of the work to Perl.

> (...) From my experiments with it all I can recommend is to try
> things until you find something that works, and to expect to have to
> make minor fixes if you upgrade to a new major version of perl.
>
> That said, I believe the correct answer is you should pass the real
> environment to _INIT3 (whether from the third arg of main or from the
> global environ), and you should pass the argv pointer you passed to
> _INIT3 to perl_parse. On some systems (VMS, OS/2) _INIT3 will modify the
> passed-in argv; on some systems (Win32, at least) it will modify the
> global environment and assume this will affect what perl_parse sees
> (ignoring the env pointer passed to _INIT3).

Yuck. I'm fixing some apparently untested code, and I won't be testing
my fix either on any of those systems:-( I'll try this for now, for the
application's set-up code:

char *embedding[] = { "", "-e", "0", NULL }; /*added NULL just in case*/
char **argv = embedding, **env = NULL;
int argc = 3;

#ifdef PERL_SYS_INIT
PERL_SYS_INIT(&argc, &argv);
#elif defined PERL_SYS_INIT3
env = environ;
PERL_SYS_INIT3(&argc, &argv, &env);
#endif

my_perl = perl_alloc();
perl_construct(my_perl);
#ifdef PERL_EXIT_DESTRUCT_END
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
#endif
perl_parse(my_perl, my_xs_init, argc, argv, env);
perl_run(my_perl);

--
Hallvard

Ben Morrow

unread,
Oct 31, 2011, 6:26:10 PM10/31/11
to

Quoth Hallvard B Furuseth <h.b.fu...@usit.uio.no>:
> Ben Morrow <b...@morrow.me.uk> writes:
>
> > Quoth Hallvard B Furuseth <h.b.fu...@usit.uio.no>:
> >> Is PERL_SYS_INIT() as portable as PERL_SYS_INIT3()? It is not
> >> documented in the manpages. I'm wondering if I should use that or
> >> pass a pointer to the possibly less portable extern char **environ;
> >> since proto.h says __attribute__nonnull__ for env.
> >
> > AFAICT they are only different on OS/2, but _INIT3 was introduced in
> > 5.6, so you should probably use it anyway. (They probably *ought* to be
> > different at least on Win32, as well, since the Win32 init code affects
> > the environment, but currently they aren't.)
>
> Sounds like it's safest to use INIT when available and INIT3 otherwise,
> then. That leaves as much as possible of the work to Perl.

_INIT is always available (at least, in all versions of perl which
support embedding).

> Yuck. I'm fixing some apparently untested code, and I won't be testing
> my fix either on any of those systems:-( I'll try this for now, for the
> application's set-up code:
<snip>

Looks sane to me.

Ben

Hallvard B Furuseth

unread,
Oct 31, 2011, 7:31:26 PM10/31/11
to
Ben Morrow writes:
> Quoth Hallvard B Furuseth <h.b.fu...@usit.uio.no>:
>> Ben Morrow <b...@morrow.me.uk> writes:
>>> Quoth Hallvard B Furuseth <h.b.fu...@usit.uio.no>:
>>>> Is PERL_SYS_INIT() as portable as PERL_SYS_INIT3()? (...)
>>>
>>> AFAICT they are only different on OS/2, but _INIT3 was introduced in
>>> 5.6, so you should probably use it anyway. (...)
>>
>> Sounds like it's safest to use INIT when available and INIT3 otherwise,
>> then. That leaves as much as possible of the work to Perl.
>
> _INIT is always available (at least, in all versions of perl which
> support embedding). (...)

I'll stick to INIT and drop INIT3 and env then, that'll equivalent to my
posted code. I misunderstood - I thought you meant INIT3 was introduced
earlier, not later.

Thank you for your help.

--
Hallvard

Ilya Zakharevich

unread,
Nov 1, 2011, 3:33:45 AM11/1/11
to
On 2011-10-31, Hallvard B Furuseth <h.b.fu...@usit.uio.no> wrote:
>> AFAICT they are only different on OS/2, but _INIT3 was introduced in
>> 5.6, so you should probably use it anyway. (They probably *ought* to be
>> different at least on Win32, as well, since the Win32 init code affects
>> the environment, but currently they aren't.)
>
> Sounds like it's safest to use INIT when available and INIT3 otherwise,
> then. That leaves as much as possible of the work to Perl.

The opposite. INIT is not supported. If it works, then only
accidentally.

env MUST be passed as the third argument to INIT3 (although it might
be coded to do something reasonable when the third argument is NULL -
do not have the source with me now to check.

Hope this helps,
Ilya

Ben Morrow

unread,
Nov 1, 2011, 8:24:04 AM11/1/11
to

Quoth Ilya Zakharevich <nospam...@ilyaz.org>:
> On 2011-10-31, Hallvard B Furuseth <h.b.fu...@usit.uio.no> wrote:
> >> AFAICT they are only different on OS/2, but _INIT3 was introduced in
> >> 5.6, so you should probably use it anyway. (They probably *ought* to be
> >> different at least on Win32, as well, since the Win32 init code affects
> >> the environment, but currently they aren't.)
> >
> > Sounds like it's safest to use INIT when available and INIT3 otherwise,
> > then. That leaves as much as possible of the work to Perl.
>
> The opposite. INIT is not supported. If it works, then only
> accidentally.

That was what I was intending to imply, but obviously I was unclear :(.

> env MUST be passed as the third argument to INIT3 (although it might
> be coded to do something reasonable when the third argument is NULL -
> do not have the source with me now to check.

The only case where INIT3 doesn't simply call INIT is OS/2, which
properly uses the global environ when passed a NULL env pointer
(complete with 'yuck' comments, I presume from you :)).

The Win32 case *ought* to use INIT3, but instead pokes values into the
environment using both CRTL's putenv and Win32's SetEnvironmentVariable,
so for portable code relying on the semantics of INIT3 (that is, trying
to pass anything other than the true global environ pointer) is
currently a bad idea.

So: Hallvard is currently right that INIT is more reliable, in practice.
In principle, it would be better if this were not the case, but I
suspect given the state of the Win32 code it isn't likely to change. The
IMP_SYS stuff just relies too much on using Win32 calls to affect the
real process environment.

Ben

Reini Urban

unread,
Dec 2, 2011, 12:54:34 PM12/2/11
to
On 11/01/2011 07:24 AM, Ben Morrow wrote:
> Quoth Ilya Zakharevich:
Your code needs to support $ENV{bla} = "bla", so you must use INIT3.

--
Reini
0 new messages