Re: plperl & sort

From: Andrew Gierth <andrew(at)tao11(dot)riddles(dot)org(dot)uk>
To: "Alex Hunsaker" <badalex(at)gmail(dot)com>
Cc: "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>, pgsql-bugs(at)postgresql(dot)org
Subject: Re: plperl & sort
Date: 2008-11-06 16:00:14
Message-ID: 8763n0hmk1.fsf@news-spur.riddles.org.uk
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

>>>>> "Alex" == Alex Hunsaker <badalex(at)gmail(dot)com> writes:

>> Then explain why the problem goes away when you build perl with
>> threading turned off.

Alex> Hrm yep i built one without threads problem disappears... Guess
Alex> Ive just been out to lunch :)

If it helps any, I've tracked down in the perl guts exactly why this
happens:

cop.h:

struct cop {
BASEOP
char * cop_label; /* label for this construct */
#ifdef USE_ITHREADS
char * cop_stashpv; /* package line was compiled in */
char * cop_file; /* file name the following line # is from */
#else
HV * cop_stash; /* package line was compiled in */
GV * cop_filegv; /* file the following line # is from */
#endif
U32 cop_seq; /* parse sequence number */
I32 cop_arybase; /* array base this line was compiled with */
line_t cop_line; /* line # of this command */
SV * cop_warnings; /* lexical warnings bitmask */
SV * cop_io; /* lexical IO defaults */
};

A COP in perl is a control operation, basically a compiled statement,
and the pointer to the current COP is used to determine all the
lexical state, including the current package. pp_sort uses
CopSTASH(PL_curcop) to get the package stash (symbol table) in order
to locate the $a and $b variables in it.

Notice, though, that without ithreads, the COP points directly to the
stash, but with ithreads, it points instead to the _name_ of the stash
(e.g. "main"). The problem arises because with Safe in use, the
package created by Safe to use as a container _thinks_ that its name
is "main" even though it's not, so the COPs compiled inside it point
to the name "main" rather than to the real name of the container.

So with ithreads enabled, pp_sort looks up the package stash by name,
gets the "main" package rather than the safe container, and creates
$main::a and $main::b to store the comparison values in. But the
compiled comparison block has its own references to the variables
which refers to the correct stash, so it all goes Horribly Wrong at
that point.

So there are three factors involved:

1) the change in layout of COP with ithreads enabled
2) the fact that Safe changes the internally-seen name of a package
3) any operation that relies on CopSTASH(PL_curcop) (I can only find a
few: sort, reset, and bless) will then behave incorrectly

However, I have no idea why Perl has this difference between threaded
and non-threaded code.

--
Andrew.

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Andrew Gierth 2008-11-06 16:03:20 Re: plperl & sort
Previous Message Alex Hunsaker 2008-11-06 15:37:58 Re: plperl & sort