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

problems with Scalar::Util

87 views
Skip to first unread message

Alex Laslavic

unread,
Mar 29, 2006, 2:35:39 PM3/29/06
to p...@perl.org
I'm trying to create a packed exe to deploy on windows servers. Build
as 'pp -o file.exe script.pl' . Builds fine, but when I run it I get:

Undefined subroutine &Scalar::Util::refaddr called at overload.pm
line92.

In an attempt to troubleshoot this, I added:
use Scalar::Util qw(refaddr);
to the script.

The script still runs fine when I run script.pl through perl, but now,
when I package the exe, and run it i get:
"refaddr" is not exported by the Scalar::Util module

This is somewhat confusing, as obviously Scalar::Util successfully
exportts refaddr when run as a perl script, but as the packaged exe, it
does not.

In Scalar/Util.pm:
refaddr is listed in @EXPORT_OK
however, sub refaddr { ... } is in a block that is only eval'd if a XS
import fails. Somehow it appears that in the pp packed version, the XS
doesn't load, but that block is not evaled either, as the refaddr
function is not exportable.

I guess I can fix it by hacking the XS load out of Scalar/Util.pm, and
forcing the sub refaddr { ... } perl function to be eval'd, but I was
sort of hoping someone else had a cleaner way to do this.


Thanks.

--
***********************************
* Alex Laslavic
* Linux Engineer
* WorldTravel BTI
* x49511
* gpg/pgp key at
* http://keys.jumpbox.net
***********************************

signature.asc

Sisyphus

unread,
Mar 29, 2006, 6:17:48 PM3/29/06
to Alex Laslavic (Lenox), p...@perl.org

----- Original Message -----
From: "Alex Laslavic (Lenox)" <Alex.L...@worldtravel.com>
To: <p...@perl.org>
Sent: Thursday, March 30, 2006 5:35 AM
Subject: problems with Scalar::Util


> The script still runs fine when I run script.pl through perl, but now,
> when I package the exe, and run it i get:
> "refaddr" is not exported by the Scalar::Util module

My understanding is that the error message is simply telling you that
"refaddr" is not listed in either @EXPORT or @EXPORT_OK.

I mean - you can have a Foo.pm that looks like:

package Foo;
use strict;
require Exporter;

our $VERSION = 0.01;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(garbage);
1;

And you can load that module from a script as:

use Foo qw(garbage);

and the fact that garbage() doesn't even exist matters not. (And you can
then build that script inot an executable and run it without any trouble -
at least on 0.90 you can.)

Could it be that the exe is picking up some version of Scalar::Util that
does not, in fact, export "refaddr". I would check that both the script and
the executable are getting hold of the same version of Scalar::Util by:

print $Scalar::Util::VERSION, "\n";

Cheers,
Rob

M.Nooning

unread,
Mar 30, 2006, 4:44:21 AM3/30/06
to Alex Laslavic (Lenox), p...@perl.org
Alex Laslavic (Lenox) wrote:
> I'm trying to create a packed exe to deploy on windows servers. Build
> as 'pp -o file.exe script.pl' . Builds fine, but when I run it I get:
>
> Undefined subroutine &Scalar::Util::refaddr called at overload.pm
> line92.
>
> In an attempt to troubleshoot this, I added:
> use Scalar::Util qw(refaddr);
> to the script.
>
> The script still runs fine when I run script.pl through perl, but now,
> when I package the exe, and run it i get:
> "refaddr" is not exported by the Scalar::Util module
>
> This is somewhat confusing, as obviously Scalar::Util successfully
> exportts refaddr when run as a perl script, but as the packaged exe, it
> does not.
>
> In Scalar/Util.pm:
> refaddr is listed in @EXPORT_OK
> however, sub refaddr { ... } is in a block that is only eval'd if a XS
> import fails. Somehow it appears that in the pp packed version, the XS
> doesn't load, but that block is not evaled either, as the refaddr
> function is not exportable.
>
> I guess I can fix it by hacking the XS load out of Scalar/Util.pm, and
> forcing the sub refaddr { ... } perl function to be eval'd, but I was
> sort of hoping someone else had a cleaner way to do this.
>
>
> Thanks.
>
>
>

Have you tried the -M switch, which will explicitly name the module?
As in
pp -o file.exe -M Scalar::Util script.pl'

Good luck

Roderich Schupp

unread,
Mar 30, 2006, 7:46:32 AM3/30/06
to Alex Laslavic (Lenox), p...@perl.org
> I'm trying to create a packed exe to deploy on windows servers.
Build
> as 'pp -o file.exe script.pl' . Builds fine, but when I run it I get:
>
> Undefined subroutine &Scalar::Util::refaddr called at overload.pm
> line92.
>
> In an attempt to troubleshoot this, I added:
> use Scalar::Util qw(refaddr);
> to the script.
>
> The script still runs fine when I run script.pl through perl, but now,
> when I package the exe, and run it i get:
> "refaddr" is not exported by the Scalar::Util module

Can you verify that Scalar::Util was correctly packed by running

unzip -l file.exe

You should see something like
...
3370 03-30-06 14:12 lib/Scalar/Util.pm
...
28770 11-02-05 09:49 lib/auto/List/Util/Util.dll

(that's right: List/Util/Util.dll is where the XS version of refaddr
comes from)

Note that I couldn't reproduce your problem with the following oneliner
(ActiveState 5.8.7 build 815, PAR 0.92, Scalar::Util 1.14)

pp -o ref.exe -e "use Scalar::Util qw/refaddr/; my $x; my $a=refaddr
\$x; print qq[refaddr=$a\n];"

Cheers, Roderich


>
> This is somewhat confusing, as obviously Scalar::Util successfully
> exportts refaddr when run as a perl script, but as the
> packaged exe, it
> does not.
>
> In Scalar/Util.pm:
> refaddr is listed in @EXPORT_OK
> however, sub refaddr { ... } is in a block that is only eval'd if a XS
> import fails. Somehow it appears that in the pp packed
> version, the XS
> doesn't load, but that block is not evaled either, as the refaddr
> function is not exportable.
>
> I guess I can fix it by hacking the XS load out of Scalar/Util.pm, and
> forcing the sub refaddr { ... } perl function to be eval'd, but I was
> sort of hoping someone else had a cleaner way to do this.
>
>
> Thanks.
>
>
>

Roderich Schupp

unread,
Mar 30, 2006, 8:27:05 AM3/30/06
to Alex Laslavic (Lenox), p...@perl.org
> I'm trying to create a packed exe to deploy on windows servers. Build
> as 'pp -o file.exe script.pl' . Builds fine, but when I run it I get:

Following up my previous mail:
Did you build pp.exe from the same version of perl and Scalar::Util
that is now on the machine you are packing script.pl?
(I just realized that pp.exe contains "built-in" versions of
Scalar/Util.pm and List/Util/Util.dll that might be older
than the ones now deployed; these are probably preferred at runtime
over other versions that may be present in the zip archive file.exe).

Cheers, Roderich

Alex Laslavic

unread,
Mar 30, 2006, 8:51:07 AM3/30/06
to p...@perl.org
On Thu, 2006-03-30 at 14:46 +0200, Roderich Schupp (ext) wrote:
> > I'm trying to create a packed exe to deploy on windows servers.
> Build
> > as 'pp -o file.exe script.pl' . Builds fine, but when I run it I get:
> >
> > Undefined subroutine &Scalar::Util::refaddr called at overload.pm
> > line92.
> >
> > In an attempt to troubleshoot this, I added:
> > use Scalar::Util qw(refaddr);
> > to the script.
> >
> > The script still runs fine when I run script.pl through perl, but now,
> > when I package the exe, and run it i get:
> > "refaddr" is not exported by the Scalar::Util module
>
> Can you verify that Scalar::Util was correctly packed by running
>
> unzip -l file.exe
>
> You should see something like
> ...
> 3370 03-30-06 14:12 lib/Scalar/Util.pm
> ...
> 28770 11-02-05 09:49 lib/auto/List/Util/Util.dll
>
> (that's right: List/Util/Util.dll is where the XS version of refaddr
> comes from)
>
> Note that I couldn't reproduce your problem with the following oneliner
> (ActiveState 5.8.7 build 815, PAR 0.92, Scalar::Util 1.14)
>
> pp -o ref.exe -e "use Scalar::Util qw/refaddr/; my $x; my $a=refaddr
> \$x; print qq[refaddr=$a\n];"
>
> Cheers, Roderich

Util.pm and Util.dll are the same version, both for the perl running on
my system, and for the files packed into the exe.

signature.asc

Alex Laslavic

unread,
Mar 30, 2006, 8:52:17 AM3/30/06
to p...@perl.org
On Thu, 2006-03-30 at 15:27 +0200, Roderich Schupp (ext) wrote:
> > I'm trying to create a packed exe to deploy on windows servers. Build
> > as 'pp -o file.exe script.pl' . Builds fine, but when I run it I get:
>
> Following up my previous mail:
> Did you build pp.exe from the same version of perl and Scalar::Util
> that is now on the machine you are packing script.pl?
> (I just realized that pp.exe contains "built-in" versions of
> Scalar/Util.pm and List/Util/Util.dll that might be older
> than the ones now deployed; these are probably preferred at runtime
> over other versions that may be present in the zip archive file.exe).
>
> Cheers, Roderich

pp.exe is from ActiveState's package manager. I suppose I can build it
by hand, and see if I get anything different, however, the correct
version of Scalar::Util is packed into the exe.

signature.asc

Roderich Schupp

unread,
Mar 30, 2006, 9:17:23 AM3/30/06
to Alex Laslavic (Lenox), p...@perl.org
> pp.exe is from ActiveState's package manager. I suppose I
> can build it
> by hand, and see if I get anything different, however, the correct
> version of Scalar::Util is packed into the exe.

Actually there are TWO versions of Scalar::Util etc in
the executable created by pp from my oneliner:
- one is in the zip archive at the end of the executable;
this one you can list/extract by running e.g. unzip on
the excutable; this one is from the machine where
you ran pp
- the other is in the data section of the executable;
you can see it with "strings file.exe";
it is copied verbatim from parl.exe where it got included
when your PAR package was built; it's part of the
pp'ed executables' bootstrap, because some perl modules
are already needed extracted before PAR can get to
the modules in the zip archive
So there's a potential mismatch, but that's just a wild guess.

Does the oneliner from my previous email have the same problem as your
script?

Cheers, Roderich

Alex Laslavic

unread,
Mar 30, 2006, 12:38:13 PM3/30/06
to p...@perl.org
On Thu, 2006-03-30 at 16:17 +0200, Roderich Schupp (ext) wrote:
> Does the oneliner from my previous email have the same problem as your
> script?

Yup. It sure does.
'refaddr' is not exported by the Scalar::Util module.

I guess I'm going to try to build the PAR bundle from source, and delete
the version from activestate. Hopefully that will get the correct
version of Scalar::Util packed into the exe.

signature.asc

Alex Laslavic

unread,
Mar 30, 2006, 1:00:48 PM3/30/06
to P...@perl.org
On Thu, 2006-03-30 at 16:17 +0200, Roderich Schupp (ext) wrote:
> Does the oneliner from my previous email have the same problem as your
> script?

You are right on. The packed exe has version 1.07, and the script is
written, and using 1.18. Now, if only I can get it to use 1.18....

use Scalar::Util 1.18 qw/refaddr/ doesn't seem to work....

Oddly, when I unzip the exe that I have created with pp, the 1.18
version is actuall in the LIB/SCALAR/ directory, but it doesn't seem to
get loaded at runtime, even with:
use Scalar::Util 1.18

Any ideas?

ls

>
> Cheers, Roderich

signature.asc

Alex Laslavic

unread,
Mar 31, 2006, 9:52:27 AM3/31/06
to p...@perl.org

For the sake of future google searchers, here is how I worked around
this.

Scalar::Util 1.07 is currently packaged into pp.exe, as it is shipped
from ActiveState PPM. You could probably recompile PAR, and pp.exe, but
I don't have Visual C++ handy, so I got around it another way.

The problem is that 1.07 was already loaded into %INC by the time my
script was executed, and I couldn't then load 1.18. My solution:

delete $INC{'Scalar/Util.pm'};
eval 'use Scalar::Util 1.18 qw(refaddr);';

This removes the 1.07 Scalar::Util, and then allows me to load 1.18 at
runtime. Not pretty, but it works.

signature.asc

Roderich Schupp

unread,
Mar 31, 2006, 10:13:26 AM3/31/06
to Alex Laslavic (Lenox), P...@perl.org
> You are right on. The packed exe has version 1.07, and the script is
> written, and using 1.18. Now, if only I can get it to use 1.18....
>
> use Scalar::Util 1.18 qw/refaddr/ doesn't seem to work....
>
> Oddly, when I unzip the exe that I have created with pp, the 1.18
> version is actuall in the LIB/SCALAR/ directory, but it
> doesn't seem to
> get loaded at runtime, even with:
> use Scalar::Util 1.18

The latter only checks that Scalar::Util should have at least
version 1.18 or die otherwise - it doesn't mean try another
Scalar::Util down the road whether it may satisfy the version
constraint.

The real problem is the way pp generates executables
(read on at your own risk :)
The basic idea is: just create a PAR archive and make it into
an executable. But in order to get to the perl modules
in the PAR we already must have PAR.pm loaded. And PAR.pm
requires other modules, e.g. Archive::Zip which require
others, e.g. Scalar::Util. So the PAR distribution
creates a standalone, statically linked, special purpose
version of the perl executable: that's basically what
parl.exe is. Before the perl interpreter in this special-built
perl variant is start, some things are done from C functions,
e.g. setup the cache directory, copy the perl shared library
into do (from C arrays contained in parl.exe) and set $ENV{PART_TEMP}
to it. Then the perl interpreter gets started with a little bootstrap
Perl code that is hand-crafted not to use any modules at all.
It extracts the modules absolutely necessary to access a PAR
archive by pure-perl means form the pp'ed executable itself
(this data is not in the PAR archive part, it has been simply
appended to the executable with special markers and headers
taht you can see if you run "strings" on the executable). Once
this modules have been extracted to the cache area, the
bootstrap code "require"s them. Now the code is able to
load the rest of the modules from the PAR archive (that has also
been appended to the executable and which is accessible by
running "unzip" on the executable) as if you had said
"perl -MPAR -Ifoo.exe ...".

The consequence is that building a PAR distribution captures
the state of your perl distribution (the version of perl itself
and that of several core and non-core modules) at the time of
the build (essentially this is frozen into parl.exe). If you install
another
version of perl or upgrade core modules (without rebuilding PAR),
pp'ed executables afterwards might behave differently than the original
scripts, because the use the captured versions. Sometimes these
differences will already show on the build machine, at other times
they only manifest themselves in another environment.

Perhaps the PAR build process should remember checksums of all
the stuff that goes into parl.exe and recheck against the
actually installed versions at pp'ing time and at least warn you
to better rebuild your PAR.

Cheers, Roderich

Message has been deleted
0 new messages