in reply to Re^4: panic: memory wrap
in thread panic: memory wrap

I was thinking of something along the lines of:
int setCallbacks( SV *rec, SV *play ) { g_rec = SvREFCNT_inc(SvRV(rec)); g_play = SvREFCNT_inc(SvRV(play)); return 0; }
ie store a direct pointer to the CV rather than a pointer to a temporary RV that points to the CV. Note that call_sv() can take a CV as an arg.

If setCallbacks() can be called more than once then you'll want to initialize the the pointers to Null, then on each call to setCallbacks(), SvREFCNT_dec() the existing g_rec and g_play if they're non-null.

Dave

Replies are listed 'Best First'.
Re^6: panic: memory wrap
by BrowserUk (Patriarch) on Nov 14, 2005 at 23:06 UTC

    Thanks again, for now, setCallback() is only being called once...

    but it still panics on the second callback, whether to the same callback as the first successful one, or a different one being called for the first time?

    That it works the first time and fails the second, still makes me think I am messing up the stack somehow?

    As you'll see below, I've had various attempts at ensuring that the stack is cleaned up. I've tried both the Inline_* macros and the XS macros to no avail?

    #! perl -slw use strict; use Inline 'NoClean', 'FORCE', 'INFO' ; use Inline Config => WARNINGS => 4; use Inline 'C' => 'DATA', NAME =>'test'; use Devel::Peek; sub recorder{ print "record: @_"; } sub player{ print "player: @_"; } print Dump \&recorder; printf "r:%x p:%x\n", \&recorder, \&player; setCallbacks( \&recorder, \&player ); record( 'test' ); play( 'test' ); __DATA__ __C__ SV *g_rec = (SV*)NULL; SV *g_play = (SV*)NULL; int setCallbacks( SV *rec, SV *play ) { printf( "r:%x p:%x\n", rec, play ); g_rec = SvREFCNT_inc( SvRV( rec ) ); g_play = SvREFCNT_inc( SvRV( play ) ); return 0; } int record( SV *m ) { // ENTER; // SAVETMPS; call_sv( g_rec, G_VOID ); // FREETMPS; // LEAVE; return 0; } int play( SV *m ) { // ENTER; // SAVETMPS; call_sv( g_play, G_VOID ); // FREETMPS; // LEAVE; return 0; } __END__ <-----------------------End of Information Section-------------------- +--------> SV = RV(0x18404b4) at 0x1949a74 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x226004 SV = PVCV(0x1824094) at 0x226004 REFCNT = 2 FLAGS = () IV = 0 NV = 0 COMP_STASH = 0x2251d0 "main" START = 0x1958cd4 ===> 11609 ROOT = 0x1958c90 XSUB = 0x0 XSUBANY = 0 GVGV::GV = 0x1959b98 "main" :: "recorder" FILE = "P:\test\test.pl" DEPTH = 0 FLAGS = 0x0 OUTSIDE_SEQ = 951 PADLIST = 0x226010 PADNAME = 0x22601c(0x1826a5c) PAD = 0x22604c(0x182ebb4) OUTSIDE = 0x2253c8 (MAIN) r:226004 p:1959c04 r:1949a74 p:2252a8 record: test panic: memory wrap at P:\test\test.pl line 18.

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Ah, I've got it! You need a PUSHMARK. You also need to push any args:
      int record( SV *m ) { PUSHMARK(SP); XPUSHs(m); PUTBACK; call_sv( g_rec, G_VOID ); return 0; }
      call_sv takes everything on the stack back to the last mark as the args for the function call. Even with no args, you need to push a mark.

      Dave.

        Thankyou! With the addition of the dSP; macro to set things up, that did the trick.

        A million calls to each of the callbacks in 20 seconds of cpu and not a sign of memory growth.

        Many thanks.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        Dave,

        Here we are years later and your advice just saved me from a new RPerl bug! Thank you so much for your wisdom.

        Perling,
        ~ Will the Chill
Re^6: panic: memory wrap
by BrowserUk (Patriarch) on Nov 15, 2005 at 23:45 UTC

    Sorry to bug you again, but I'm trying to work out how I could have gotten to the working solution without your having to lead me by the nose.

    Note that call_sv() can take a CV as an arg

    Is this written down somewhere I should have been looking? Or is it something you picked up/worked out from experience.

    Also, you led me to using g_rec = SvREFCNT_inc(SvRV(rec)); to safely replicate the CV* for the callback and detailed the need to decrement the refcount before replacing the CV*, if the callback addesses are changed.

    In perlcall, they suggest a combination of newSVsv() and SvSetSV() to do this, which if I've unwound the macros correctly, amounts to much the same thing, except that your way sheds a level of indirection?

    Did I understand that right? Can you see any particular advantage of one over the other?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Bother, I replied to this once, but previewed and then forgot to submit :-(

      Anyway, the short answer is that I'm an internals guy rather than an XS guy, so I tend to know internal ways of doing things rather than official API ways of doing things.

      Dave.