Eyck has asked for the wisdom of the Perl Monks concerning the following question:

I've been bitten by a side effect, here's example code from documentation of Net::SSLeay::Handle:

my $socket \*S1; if ($scheme eq "https") { tie(*S2, "Net::SSLeay::Handle", $socket); $socket = \*S2; }

This works OK, unfortunatelly I used it in a library inside object, so when you brought two life multiple such objects

for $sth (@sth) { my $object=new STH; $objects{$sth}=$object; };

the whole shebang failed miserably (the last invocation of $object hides every other SSLeay::Handle (there is only one \*S2)

Now I'm trying to fix the code, here's my attempt which seems to work at the moment:

{my $io=new IO::Handle; tie(*$io, "Net::SSLeay::Handle", $socket);$so +cket = \*$io;}; { my $io=new IO::Handle; tie(*$io, "Net::SSLeay::Handle", $socket); $socket = \*$io; };

AFAIK this works because every $io=new IO::Handle generates unique identifier, so my code above might be replaced with

$global-net-ssleay-counter++; tie(*$global.....
and it would still work, and wouldn't depend on chance (I hope two IO::Handle->new()don't get the same identifier).

What is the proper solution to this? How should I use Net::SSLeay::Handle?

Replies are listed 'Best First'.
Re: Globs and globals
by BrentDax (Hermit) on Jan 25, 2005 at 07:58 UTC

    The easiest way might be to just localize S1 and S2 first:

    local(*S1, *S2); in your first example...

    OTOH, I don't think my $socket \*S1 is valid Perl--maybe there's an equal sign missing between $socket and \*S1?

    --Brent Dax
    There is no sig.

      This advice is factually incorrect.

      GLOB is a glob, and local doesen't help here ( besides providing false sense of security )

      my $socket=\*S1; print "Orig:",$socket,"\n"; { local(*S1, *S2); my $s=\*S1; print "Local: ",$s,"\n"; }
      Local: GLOB(0x8160be4)

        Odd--you're right, though I can't figure out why. The docs seem to say that you get a new glob when you localize:

        The construct local *name; creates a whole new symbol table entry for the glob "name" in the current package. That means that all variables in its glob slot ($name, @name, %name, &name, and the "name" filehandle) are dynamically reset.

        In any case, the following does work correctly:

        open(S1, "/dev/null"); $a=*S1{IO}; { local(*S1); open(S1, "/dev/null"); $b=*S1{IO}; } print "$a $b\n";
        IO::Handle=IO(0x101536f8) IO::Handle=IO(0x1013cdec)

        --Brent Dax
        There is no sig.

Re: Globs and globals
by nobull (Friar) on Jan 25, 2005 at 12:39 UTC
    What is the proper solution to this?

    The proper solution would be for Net::SSLeay::Handle to provide a new() method.

    Absent that you solution using IO::Handle is probably the best except I'd probably simplfy $socket=\*$io to $socket=$io.

Re: Globs and globals
by dragonchild (Archbishop) on Jan 25, 2005 at 14:09 UTC
    You could also use gensym (part of Symbol), the way IO::Handle does. (Read the code ... it's actually quite simple.)

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.