1

Please note the following minimal working example:

use warnings;
use strict;
use IPC::Shareable;
use Data::Printer;

IPC::Shareable->clean_up;


my $sharevar1 = "a";
my $sharevar2;


print "A: $sharevar1 $sharevar2\n";
p($sharevar1);
p($sharevar2);


my $glue1 = 'glu1';
my $glue2 = 'glu2';

my %options = (
  create    => 1, #'yes',
  exclusive => 0,
  mode      => 0644, #0644,
  destroy   => 1, # 'yes',
);

my $sharevar_handle1 = tie $sharevar1, 'IPC::Shareable', $glue1 , \%options ; #

print "B1: $sharevar1 $sharevar2 - $sharevar_handle1\n";

my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; #

print "B2: $sharevar1 $sharevar2 - $sharevar_handle2\n";

p($sharevar1);
p($sharevar2);


$sharevar1 = "b";
#~ $sharevar1 = "AOE" . \$sharevar2;
$sharevar2 = 20;

print "C: ";
print "- $sharevar1 $sharevar2\n";
p($sharevar1);
p($sharevar2);

When I run this, I get an output like below - which is as expected:

Use of uninitialized value $sharevar2 in concatenation (.) or string at tt.pl line 13.
A: a 
"a"
undef
Use of uninitialized value $sharevar1 in concatenation (.) or string at tt.pl line 30.
Use of uninitialized value $sharevar2 in concatenation (.) or string at tt.pl line 30.
B1:   - IPC::Shareable=HASH(0xa1dc1b8)
Use of uninitialized value $sharevar1 in concatenation (.) or string at tt.pl line 34.
Use of uninitialized value $sharevar2 in concatenation (.) or string at tt.pl line 34.
B2:   - IPC::Shareable=HASH(0xa215b10)
undef (tied to IPC::Shareable)
undef (tied to IPC::Shareable)
C: - b 20
"b" (tied to IPC::Shareable)
20 (tied to IPC::Shareable)

 

However, if now I try to uncomment the "$sharevar1 = "AOE" . \$sharevar2;" line, while commenting out the "$sharevar1 = "b";" above it; then the output I get is mostly the same, except at the end:

...
B2:   - IPC::Shareable=HASH(0x852fb20)
undef (tied to IPC::Shareable)
undef (tied to IPC::Shareable)
Can't use string ("AOESCALAR(0x836bf88)") as a SCALAR ref while "strict refs" in use at /usr/local/share/perl/5.10.1/IPC/Shareable.pm line 741.
C: $ 

Now, the thing is that this "Can't use string ..." actually causes a crash... Apparently if a tied variable ever gets assigned a reference via \, it gets a value like SCALAR(0x836bf88) as a string, which apparently gets interpreted by Perl afterwards to mean an address... ?!

And I thought that Perl would in that case match the starting part (SCALAR(...) of the string - and so I tried to cheat by prepending string "AOE" - but the strange thing is, Perl still noticed (as if it is looking for some regex for "0x withing parenthesis" kinda match): "Can't use string ("AOESCALAR(0x836bf88)") as a SCALAR ref" ...

 

My question is - is my reasoning about how Perl and IPC::Shareable interpret an address (which is otherwise stored as a "string") correct (no, see edit below; yes, see post); and regardless if it is, how would I go about storing an address into an IPC::Shareable?

Many thanks in advance for any answers,
Cheers!

EDIT: Well, apparently, normally all works OK with printing string variables that contain string adresses - so this problem is IPC::Shareable specific, I guess:

  DB<1> $ttt = "aa"
  DB<2> p $ttt
aa
  DB<3> $eee = \$ttt
  DB<4> p $eee
SCALAR(0xa382668)
  DB<5> $eee = "erw".\$ttt
  DB<6> p $eee
erwSCALAR(0xa382668)
  DB<7> q
Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278

2 Answers2

1

I could help you better if you would upgrade to the latest version (0.60) of IPC::Shareable. I have no access to a Unix box to try this at present, but there is nothing significant at line 741 of the current version.

You should be aware that, when you are dealing with tied variables, you are just interfacing with a standard API that looks like a Perl variable. So in writing $sharevar1 = "AOE" . \$sharevar2 you are actually calling IPC::Shareable::STORE($sharevar1, "AOE" . \$sharevar2) which can do pretty much what it wants.

What I do see in the module is code that checks whether the value to be assigned (to a tied scalar) is a reference value, and if so ties it to IPC::Shareable if it isn't already tied. The type to use in dereferencing the value is established by checking the stringified reference against /SCALAR/ etc. and although I don't see how it applies to the behaviour you are seeing (I would expect the string 'AOESCALAR(0x836bf88)' to be recognized as not being a reference and so not subject to regex checking) I am sure it is contributory. Maybe it is something that has been fixed in my version?

There is a lot of room for error in this methodology, not least that variables tied to other classes will throw the whole thing out completely. I suggest you upgrade and see if the latest version supports what you want to do.

Remember though that this has nothing to do with core Perl, and everything to do with the module incompletely emulating the interface to Perl scalars.

Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Hi @Borodin, thanks for your answer! I've tried updating, `perl` says: `IPC::Shareable is up to date (0.6).` I've updated [my post](http://stackoverflow.com/a/10668741/277826); I can confirm that as long as capital "`SCALAR`" is not present, variable can be printed (even with "`scalar`" in lowercase); I too would expect "_recognized as not being a reference_", but apparently it isn't so, at least on my Ubuntu box. Many thanks again - cheers! – sdaau May 19 '12 at 21:51
0

Well, turns out I was wrong about being wrong :)

Turns out, this problem is - after all - related to string parsing; namely, the keyword SCALAR in uppercase is checked; here is the corresponding changed portion of the code in OP:

p($sharevar1);
p($sharevar2);


#~ $sharevar1 = "b";
#~ $sharevar1 = substr "AOE" . \$sharevar2, 2, 7; # Can't use string ("ESCALAR") as a SCALAR ref
#~ $sharevar1 = substr "AOE" . \$sharevar2, 5, 10; # "ALAR(0x878", passes OK
$sharevar1 = lc \$sharevar2; # lowercase works too
$sharevar2 = 20;

print "C: ";
print "- $sharevar1 $sharevar2\n";
p($sharevar1);
p($sharevar2);

Note that anytime you have SCALAR, even if you don't have numbers for address (as in "ESCALAR"), the strict use error is thrown.

However, if the keyword SCALAR is not there in its entirety - and even if it is in lowercase - then the error disappears; this is the end of the terminal log now:

...
B2:   - IPC::Shareable=HASH(0x9ca2e58)
undef (tied to IPC::Shareable)
undef (tied to IPC::Shareable)
C: - scalar(0x9adef88) 20
"scalar(0x9adef88)" (tied to IPC::Shareable)
20 (tied to IPC::Shareable)

Well, hope this was it - but as I don't really understand this mechanism yet, any better clarifications are welcome,
Cheers!


EDIT: Just discovered another thing; sometimes you may do:

my $sharevar2;
my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; #
print($sharevar2);

I've just noticed that sometimes (but not always, and cannot really say when); tie instead of an 'undef', will set the $sharevar2 variable to something like "SCALAR()" or "ARRAY()" - in which case, the very print($sharevar2); statement will fail.

You cannot debug this other way, but to use Data::Printer's p() on not $sharevar2 (cause attempting to print it anyhow will fail) - but instead, on $sharevar_handle2:

my $sharevar2;
my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; #
print "2 "; p($sharevar_handle2);

... and then the output may be something like:

...
2 IPC::Shareable  {
    Parents       Exporter
    Linear @ISA   IPC::Shareable, Exporter
    public methods (31) : ....
    private methods (11) : ....
    internals: {
        _data   \ "ARRAY(0xa21e788)",
        _iterating   "",
...

In that case, you're sure $sharevar2 is set to "ARRAY(0xa21e788)", and therefore will always cause failure when one attempts to print it. Note that something like this can be caused by having a command where $sharevar2 is assigned to a reference (i.e. = \$somevar;) much later in the code; and this causality may not always be obvious.

For a temporary fix, simply set the "misbehaving" variable to undef after tie - and that should allow easier tracking of where assignment to a reference has happened:

my $sharevar2;
my $sharevar_handle2 = tie $sharevar2, 'IPC::Shareable', $glue2 , \%options ; 
# if here $sharevar2 somehow becomes "ARRAY(0x88417c8)" instead of undef; reset
print "1 "; p($sharevar_handle2); # would show "ARRAY(0x88417c8)"
$sharevar2 = undef;
print "2 "; p($refvarstr_handle); # should show undef
p($sharevar2); # should not crash, cause it's now ARRAY anymore, but undef

Also related: can't use string as a SCALAR ref while strict refs - perlmonks.org

sdaau
  • 36,975
  • 46
  • 198
  • 278