Fix latent refcounting bug

It can be reproduced by enabling the Perl debugger inside a PSGI application:

    {
        package DB;

        sub DB { }
        sub sub { &$sub }
    }

    $^P = 0x73f;

    sub { [200, ['Content-Type' => 'text/plain'], ['Hello World']] }

For every request the following warnings are emitted:

    Attempt to free unreferenced scalar: SV 0xfea6e8, Perl interpreter: 0xd534a0.
    Attempt to free unreferenced scalar: SV 0xfea718, Perl interpreter: 0xd534a0.

where the unreferenced scalars are the uwsgi::input/uwsgi::error instances
created in build_psgi_env.

The calling convention for Perl subroutines is that the values pushed on the
stack must be mortalized in the callee, and if the caller wants to retain them,
it must do a SvREFCNT_inc to undo the effect of the mortalization.

Before this patch XS_input/XS_error were not mortalizing the value, and
uwsgi_perl_obj_new was not incrementing the reference count, so the two bugs
balanced each other.

When running under debugger, Perl forwards all function/method calls to
DB::sub, which causes a mortal copy of the return value of
uwsgi::input/error::new to be pushed on the stack. The value is cleared by the
FREETMPS at the end of uwsgi_perl_obj_new, and the freed value is added to the
environment hash. The warning is emitted at the end of the request when the
environment hash is freed and Perl notices that some of the values has been
already freed.
This commit is contained in:
Mattia Barbon
2014-11-02 06:13:20 +01:00
committed by Roberto De Ioris
parent f059a69312
commit 309f449a43
2 changed files with 4 additions and 1 deletions
+3
View File
@@ -30,6 +30,7 @@ XS(XS_error) {
else {
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->error)[0]);
}
sv_2mortal(ST(0));
XSRETURN(1);
}
@@ -46,6 +47,7 @@ XS(XS_input) {
else {
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->input)[0]);
}
sv_2mortal(ST(0));
XSRETURN(1);
}
@@ -85,6 +87,7 @@ XS(XS_stream)
else {
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->stream)[0]);
}
sv_2mortal(ST(0));
XSRETURN(1);
}
else {
+1 -1
View File
@@ -114,7 +114,7 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
SPAGAIN;
newobj = POPs;
newobj = SvREFCNT_inc(POPs);
PUTBACK;
FREETMPS;
LEAVE;