Discussion:
Am I checking for undef in the wrong way?
(too old to reply)
Erland Sommarskog
2009-07-22 20:48:20 UTC
Permalink
I have an issue with an XS module of mine. I lean towards that it is a
bug in threads::shared, but maybe I am doing something wrong?

To show the issue, I have this silly XS routine:

void
arraytest(arrayref)
SV * arrayref
CODE:
{
AV * av = (AV *) SvRV(arrayref);
SV ** svp = av_fetch(av, 0, 0);
SV * sv = *svp;

warn ("SvOK = %d\n", SvOK(sv));
warn ("SvIV = %d\n", SvIV(sv));
warn ("SvOK = %d\n", SvOK(sv));
}

The main script runs:

my $arrayref = [5678];
arraytest($arrayref);
my $shared_arrayref : shared = shared_clone($arrayref);
arraytest($shared_arrayref);

The output is:

SvOK = 4352
SvIV = 5678
SvOK = 4352
SvOK = 0
SvIV = 5678
SvOK = 4096

That is, when I send in a regular array reference, results are as
expected. But when the reference is a shared object, SvOK first
returns 0. When I retrieve the value with SvIV I get the correct
value nevertheless, and next time SvOK returns a true value!

Am I doing somethinug wrong? Or should I file a bug for threads::shared?

If it is a bug, any suggestion for a workaround? In the real module, the
value can be of any type, so SvIV does not seem like a good idea.

This happens on Win32 with ActivePerl builds 1005. I attach my test
module and test script (which also shows the same thing happens with a
hash reference.)
--
Erland Sommarskog, Stockholm, ***@sommarskog.se
Jan Dubois
2009-07-22 21:03:46 UTC
Permalink
Post by Erland Sommarskog
I have an issue with an XS module of mine. I lean towards that it is a
bug in threads::shared, but maybe I am doing something wrong?
void
arraytest(arrayref)
SV * arrayref
{
AV * av = (AV *) SvRV(arrayref);
SV ** svp = av_fetch(av, 0, 0);
SV * sv = *svp;
SvGETMAGIC(sv);
Post by Erland Sommarskog
warn ("SvOK = %d\n", SvOK(sv));
warn ("SvIV = %d\n", SvIV(sv));
warn ("SvOK = %d\n", SvOK(sv));
}
That is, when I send in a regular array reference, results are as
expected. But when the reference is a shared object, SvOK first
returns 0. When I retrieve the value with SvIV I get the correct
value nevertheless, and next time SvOK returns a true value!
Am I doing somethinug wrong? Or should I file a bug for threads::shared?
This can happen with other magical SVs too. You must call SvGETMAGIC()
before you can trust the SVf_?OK flags. SvIV() will do this as a side
effect.

Cheers,
-Jan
Erland Sommarskog
2009-07-23 21:35:53 UTC
Permalink
Post by Jan Dubois
This can happen with other magical SVs too. You must call SvGETMAGIC()
before you can trust the SVf_?OK flags. SvIV() will do this as a side
effect.
Thus, in any place where I receive a value of which I don't know the
origin, I should call SvGETMAGIC first. I could then just as well
have

BOOL sv_isdefined(SV *sv) {
SvGETMAGIC(sv);
return SvOK(sv);
}

Or would this lead in my new problems?

Thanks a lot for your quick answer!
--
Erland Sommarskog, Stockholm, ***@sommarskog.se
Jan Dubois
2009-07-23 22:30:57 UTC
Permalink
Post by Erland Sommarskog
Post by Jan Dubois
This can happen with other magical SVs too. You must call SvGETMAGIC()
before you can trust the SVf_?OK flags. SvIV() will do this as a side
effect.
Thus, in any place where I receive a value of which I don't know the
origin, I should call SvGETMAGIC first. I could then just as well
have
BOOL sv_isdefined(SV *sv) {
SvGETMAGIC(sv);
return SvOK(sv);
}
Or would this lead in my new problems?
You should pass in the Perl context so it works under MULTIPLICITY (and
by extension under USE_ITHREADS):


#define sv_isdefined(sv) my_is_defined(aTHX_ sv)

static BOOL
my_sv_isdefined(pTHX_ SV *sv) {
...
}

Drop the "static" and move the #define into a header file if you need to
call it from more than one source file.

Cheers,
-Jan
Erland Sommarskog
2009-07-24 20:36:16 UTC
Permalink
Post by Jan Dubois
You should pass in the Perl context so it works under MULTIPLICITY (and
#define sv_isdefined(sv) my_is_defined(aTHX_ sv)
static BOOL
my_sv_isdefined(pTHX_ SV *sv) {
...
}
I read about MULTIPLICITY i perlguts, and as I understand it, I would
only need to do the above, if I use PERL_NO_GET_CONTEXT, which I don't.
Yes, I get the hint that I should if I want better performance, so I guess
I should add it to the to-do list.
--
Erland Sommarskog, Stockholm, ***@sommarskog.se
Bolhar-Nordenkampf Ferdinand
2009-07-24 07:04:34 UTC
Permalink
Post by Erland Sommarskog
Thus, in any place where I receive a value of which I don't know the
origin, I should call SvGETMAGIC first. I could then just as well
have
BOOL sv_isdefined(SV *sv) {
SvGETMAGIC(sv);
return SvOK(sv);
}
Or would this lead in my new problems?
Thanks a lot for your quick answer!
If a scalar has a type of MAGIC:

(SvTYPE(sv) == SVt_PVMG) and

has the SVs_GMG flag set in its SvFLAGS field:

((SvFLAGS(sv) & SVs_GMG)

you should invoke SvGETMAGIC. Otherwise, it isn't required.

Greetings, Ferry
--

Ing. Ferry Bolhár-Nordenkampf
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-mail: ferdinand.bolhar-***@wien.gv.at
Jan Dubois
2009-07-24 07:48:24 UTC
Permalink
Post by Bolhar-Nordenkampf Ferdinand
Post by Erland Sommarskog
Thus, in any place where I receive a value of which I don't know the
origin, I should call SvGETMAGIC first. I could then just as well
have
BOOL sv_isdefined(SV *sv) {
SvGETMAGIC(sv);
return SvOK(sv);
}
Or would this lead in my new problems?
Thanks a lot for your quick answer!
(SvTYPE(sv) == SVt_PVMG) and
((SvFLAGS(sv) & SVs_GMG)
you should invoke SvGETMAGIC. Otherwise, it isn't required.
That doesn't make much sense; you would just duplicate the SvFLAGS test.
SvGETMAGIC(sv) already expands to

if (SvFLAGS(sv) & SVs_GMG)
mg_get(sv);

Likewise there is no point in checking SvTYPE(sv) because only
SVs with attached magic should have the SVs_GMG set.

Cheers,
-Jan
Loading...