Discussion:
Callback to a Perl sub that dies (from XS)
(too old to reply)
Christian Hoermann
2007-07-12 08:46:44 UTC
Permalink
Hello everyone,

I want to call a perl constructor, which also calls die (with the
object). For example, in perl code:

MyClass->Raise($err_code, $err_string);

Now, the question is whether the following code would leak memory
(under mod_perl) or work as intended. In other words, if the sub calls
die (the intended effect), will the temporaries still get cleaned up
in a persistent environment such as mod_perl?

void my_c_func(int err_code, char *err_string)
{
dSP;

ENTER;
SAVETMPS;

PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv("MyClass", 0)));
XPUSHs(sv_2mortal(newSViv(err_code)));
XPUSHs(sv_2mortal(newSVpv(err_string, 0)));
PUTBACK;

call_method("Raise", G_DISCARD);

FREETMPS;
LEAVE;
}

I also have one more unrelated question: Using SvPV(sv, len) on a
unicode string, len is guaranteed to be the byte length, not unicode
length, right?

By the way, I have read perlcall, perlguts and perlxs and related documentation.

Thank you for your time.


Best Regards,

Christian
Muppet
2007-07-13 00:42:02 UTC
Permalink
Post by Christian Hoermann
Now, the question is whether the following code would leak memory
(under mod_perl) or work as intended. In other words, if the sub calls
die (the intended effect), will the temporaries still get cleaned up
in a persistent environment such as mod_perl?
sv_2mortal() exists to ensure that things that go onto the stack are
cleaned up if they are not otherwise stored.

As i understand it:

1. Create a new sv with refcount 1.
2. sv_2mortal() makes that refcount 0.
3. Put it on the stack, no refcount change.
4. call_sv(), stuff happens. there's a die().
5. somewhere, either in the die() or after, perl will free
everything on the orphaned stack, and your temps will be cleaned up.

Anyone with better internals knowledge than i (likely many on this
list), please correct me.

--
It's all very complicated and would take a scientist to explain it.
-- MST3K
Christian Hoermann
2007-07-13 13:27:21 UTC
Permalink
Post by Muppet
1. Create a new sv with refcount 1.
2. sv_2mortal() makes that refcount 0.
3. Put it on the stack, no refcount change.
4. call_sv(), stuff happens. there's a die().
5. somewhere, either in the die() or after, perl will free
everything on the orphaned stack, and your temps will be cleaned up.
Thank you for your explanation. It makes sense and I didn't think
there would be a memory issue, but I wanted to make sure, because
finding these types of bugs at a later stage might be difficult.

Christian
s***@gmail.com
2007-07-17 23:08:03 UTC
Permalink
Post by Muppet
sv_2mortal() exists to ensure that things that go onto the stack are
cleaned up if they are not otherwise stored.
1. Create a new sv with refcount 1.
2. sv_2mortal() makes that refcount 0.
3. Put it on the stack, no refcount change.
4. call_sv(), stuff happens. there's a die().
5. somewhere, either in the die() or after, perl will free
everything on the orphaned stack, and your temps will be cleaned up.
More or less. sv_2mortal() does not actually make the refcount 0
immediately. It makes it zero "sometime later". It's a deferred
decrement of the reference count.

So I would describe it:

1. Create a new sv with refcount 1.
2. sv_2mortal() queues up a refcount decrement for the next FREETMPS
at this level of the ENTER,SAVETMPS..FREETMPS,LEAVE stack.
3. Put it on the stack, no refcount change. (A dangerous optimization
that core Perl uses.)
4. call_sv(), stuff happens. There's a die(). call_sv() returns with
$@ (ERRSV) set to whatever you died with. Nothing happens to the
mortal SVs because anything within the call_sv() has its own
ENTER,SAVETMPS scope.
5. In your FREETMPS, the deferred refcount decrement happens and
changes the refcount from 1 to 0. The object is freed.

Loading...