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

[perl #51370] Clearing magic (was: [#perl 51370] length($@)>0 for empty $@ if utf8 is in use)

Thread Next
From:
Animator via RT
Date:
April 27, 2008 05:30
Subject:
[perl #51370] Clearing magic (was: [#perl 51370] length($@)>0 for empty $@ if utf8 is in use)
Message ID:
rt-3.6.HEAD-23612-1209217552-38.51370-15-0@perl.org
On Mon Mar 03 06:41:54 2008, pajas@ufal.mff.cuni.cz wrote:
> Perl seems to cache character length of scalars, but in case of $@
> it does not reset it after a successfull eval. Here is an example.
> 
> ...

Hello,

I took a look at this bug-report and the magic assoicated with $@ does 
not get cleared.

I did some testing on how to turn it off but I'm not sure what 'the 
correct way' is. (Therefor there is no patch)
Can someone offer some guidance?


The test case:

#!/usr/bin/perl -l

use utf8;
use Devel::Peek
eval { 1 };
Dump($@);
eval { die "\x{a10d}"};
$_ = length $@;
eval { 1 };
Dump($@);  


The current output (on blead):

SV = PV(0x8130f04) at 0x812ffd8
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x813d8d0 ""\0
  CUR = 0
  LEN = 240
SV = PVMG(0x813d390) at 0x812ffd8
  REFCNT = 1
  FLAGS = (SMG,POK,pPOK,UTF8)
  IV = 0
  NV = 0
  PV = 0x813d8d0 ""\0 [UTF8 ""]
  CUR = 0
  LEN = 240
  MAGIC = 0x8145e38
    MG_VIRTUAL = &PL_vtbl_utf8
    MG_TYPE = PERL_MAGIC_utf8(w)
    MG_LEN = 23

Which shows that the flags SMG and UTF8 are (still) set and the 
IV,NV,MAGIC is also set.



In pp_ctl.c, Perl_create_eval_scope I modified this code:

    if (flags & G_KEEPERR)
        PL_in_eval |= EVAL_KEEPERR;
    else
        sv_setpvn_mg(ERRSV,"",0);

Into:

    if (flags & G_KEEPERR)
        PL_in_eval |= EVAL_KEEPERR;
    else {
        sv_setpvn_mg(ERRSV,"",0);
    }


Which turned the output into:

SV = PV(0x814e3a8) at 0x81504f8
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x815cbc0 ""\0
  CUR = 0
  LEN = 240
SV = PVMG(0x815c870) at 0x81504d8
  REFCNT = 1
  FLAGS = (SMG,POK,pPOK,UTF8)
  IV = 0
  NV = 0
  PV = 0x815cba0 ""\0 [UTF8 ""]
  CUR = 0
  LEN = 240
  MAGIC = 0x8167638
    MG_VIRTUAL = &PL_vtbl_utf8
    MG_TYPE = PERL_MAGIC_utf8(w)
    MG_LEN = -1


Which makes the length 0 but it stil lhas all the extra flags attached 
to it.


Next: I changed it into

    if (flags & G_KEEPERR)
        PL_in_eval |= EVAL_KEEPERR;
    else {
        sv_setpvn_mg(ERRSV,"",0);
        if (SvMAGICAL(ERRSV)) {  
            mg_clear(ERRSV);
        }
    }  

Output:

SV = PV(0x814e3a8) at 0x81504f8
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x815cbc0 ""\0
  CUR = 0
  LEN = 240
SV = PVMG(0x815c890) at 0x81504f8
  REFCNT = 1
  FLAGS = (SMG,POK,pPOK,UTF8)
  IV = 0
  NV = 0
  PV = 0x815cbc0 ""\0 [UTF8 ""]
  CUR = 0
  LEN = 240
  MAGIC = 0x8167658
    MG_VIRTUAL = &PL_vtbl_utf8
    MG_TYPE = PERL_MAGIC_utf8(w)
    MG_LEN = -1


Which is the same as the previous output.



Next:

    if (flags & G_KEEPERR)
        PL_in_eval |= EVAL_KEEPERR;
    else {
        sv_setpvn_mg(ERRSV,"",0);
        if (SvMAGICAL(ERRSV)) {  
            mg_free(ERRSV);
        }
    }  

Output:

SV = PV(0x814e3a8) at 0x81504f8
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x815cbc0 ""\0
  CUR = 0
  LEN = 240
SV = PVMG(0x815c890) at 0x81504f8
  REFCNT = 1
  FLAGS = (SMG,POK,pPOK,UTF8)
  IV = 0
  NV = 0
  PV = 0x815cbc0 ""\0 [UTF8 ""]
  CUR = 0
  LEN = 240


Now the MAGIC is gone, but the UTF8 and the flags are still set.



Next:

    if (flags & G_KEEPERR)
        PL_in_eval |= EVAL_KEEPERR;
    else {
        sv_setpvn_mg(ERRSV,"",0);
        if (SvMAGICAL(ERRSV)) {  
            mg_free(ERRSV); 
        }
        SvPOK_only(ERRSV);
    }

Output:

SV = PV(0x814e3c8) at 0x8150518
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x815cbe0 ""\0
  CUR = 0
  LEN = 240
SV = PVMG(0x815c8b0) at 0x8150518
  REFCNT = 1
  FLAGS = (SMG,POK,pPOK)
  IV = 0
  NV = 0
  PV = 0x815cbe0 ""\0
  CUR = 0
  LEN = 240


Now the MAGIC and the UTF8 are gone but the SMG flag is still there.



Next:

    if (flags & G_KEEPERR)
        PL_in_eval |= EVAL_KEEPERR;
    else {
        sv_setpvn_mg(ERRSV,"",0);
        if (SvMAGICAL(ERRSV)) {  
            mg_free(ERRSV); 
            mg_clear(ERRSV);
        }
        SvPOK_only(ERRSV);
    }


Output:

SV = PV(0x814e3e8) at 0x8150538
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x815cc00 ""\0
  CUR = 0
  LEN = 240
SV = PVMG(0x815c8d0) at 0x8150538
  REFCNT = 1
  FLAGS = (POK,pPOK)
  IV = 0
  NV = 0
  PV = 0x815cc00 ""\0
  CUR = 0
  LEN = 240

The MAGIC is gone, the UTF8 is gone, the SMG flag is gone.


Next: (back to sv_setpvn instead of sv_setpvn_mg)

    if (flags & G_KEEPERR)
        PL_in_eval |= EVAL_KEEPERR;
    else {
        sv_setpvn(ERRSV,"",0);
        if (SvMAGICAL(ERRSV)) {  
            mg_free(ERRSV); 
            mg_clear(ERRSV);
        }
        SvPOK_only(ERRSV);
    }


Output:

SV = PV(0x814e3e8) at 0x8150538
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x815cc00 ""\0
  CUR = 0
  LEN = 240
SV = PVMG(0x815c8d0) at 0x8150538
  REFCNT = 1
  FLAGS = (POK,pPOK)
  IV = 0
  NV = 0
  PV = 0x815cc00 ""\0
  CUR = 0
  LEN = 240


So, is this the correct way?


And: should this be changed in every place where sv_setpvn(ERRSV,"",0) 
is used?

grep -r 'sv_setpvn(ERRSV,"",0);' * # shows that it is used in 9 other 
places


And: if it has to change everywhere then what would the best approach 
be?
Placing it in a separate function? (If so, in what file, what 
name, ...) 


(If I know the correct way I'll create a patch with a test case for it)


Kind regards,

Bram


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About