develooper Front page | perl.perl5.porters | Postings from January 2008

not a pad error

Thread Next
Nicholas Clark
January 26, 2008 06:21
not a pad error
Message ID:
pp_enteriter has this:

	svp = &PAD_SVl(PL_op->op_targ);		/* "my" variable */
	iterdata = INT2PTR(void*, PL_op->op_targ);
	cxtype |= CXp_PADVAR;

I trace it back to this:

Change 7858 by gsar@onru on 2000/11/25 20:52:17

	C<foreach my $x ...> in pseudo-fork()ed process may diddle
	parent's memory; fix it by keeping track of the actual pad
	offset rather than a raw pointer (this change is probably also
	relevant to non-ithreads case to avoid fallout from reallocs of
	the pad array, but is currently only enabled for the ithreads
	case in the interests of minimal disruption to existing "well
	tested" code)

I think I can see why it is needed for the dup case for ithreads, given that
previously the address to restore would be "duplicated" with

	case SAVEt_SPTR:			/* SV* reference */
	    ptr = POPPTR(ss,ix);
	    TOPPTR(nss,ix) = any_dup(ptr, proto_perl);
	    sv = (SV*)POPPTR(ss,ix);
	    TOPPTR(nss,ix) = sv_dup(sv, param);

and any_dup() is, well, scary:

void *
Perl_any_dup(pTHX_ void *v, const PerlInterpreter *proto_perl)
    void *ret;

    if (!v)
	return (void*)NULL;

    /* look for it in the table first */
    ret = ptr_table_fetch(PL_ptr_table, v);
    if (ret)
	return ret;

    /* see if it is part of the interpreter structure */
    if (v >= (void*)proto_perl && v < (void*)(proto_perl+1))
	ret = (void*)(((char*)aTHX) + (((char*)v) - (char*)proto_perl));
    else {
	ret = v;

    return ret;

Note that in this case, the address to 'dup' is inside the memory allocated by
an array. The context stack has no idea of this, and no way to find out. So it
won't change it.

Sarathy comments

    avoid fallout from reallocs of the pad array

which is actually something I wondered when looking at the code before
working out which patch last changed it. But I tried this:

    #!perl -w
    use strict;
    sub boom {
        my $v;
        my $x = "aaaaa";
        for $v (0..1) {
            for (0..9999) {
                eval "my \$$x = 1";

which I thought would reallocate the pad, invalidating the pointer on the
save stack, and hence cause "fun" at scope exit, but it doesn't.

What am I missing? Is Sarathy's assumption wrong for some reason?
Or is there a latent bug here for the unthreaded case, and if so, how do I
provoke it?

Nicholas Clark

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About