jalopeura has asked for the wisdom of the Perl Monks concerning the following question:

I'm having a problem with some XS that is some kind of perl stack issue. It doesn't always happen in the same XSUB, but I always get a usage error from the XSUB when it happens. The fact that it doesn't happen in the same XSUB means I don't know what code is causing it, so I can't supply code.

In one case, I have CPP code calling a method on a perl object; I have provided a base class with a default XS version of that method. If I don't provide that method in my subclass, the error can actually happen without going to Perl code at all.

I am able to reproduce the error, and so I examined the items variable (by altering the c file generated from the XS and then recompiling), and it was negative. However, these are method calls (but not always from the same class), so the blessed reference HAS to be on the stack, or Perl wouldn't have called the XSUB in the first place.

Since this is XS, my first thought is that I've messed up refcounts and mortality. But would that affect the items variable? What else might be the problem?

Replies are listed 'Best First'.
Re: Perl stack issue
by BrowserUk (Patriarch) on Jun 06, 2011 at 22:02 UTC
    so I can't supply code.

    Without code that demonstrates the problem all we can do is sympathise.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      I was hoping someone with a bit of experience would recognize the problem. (I mean experience with a similar problem, not experience in general.) Surely, someone somewhere has experienced this kind of stack problem and can give me a hint as to where the problem lies.

      As I said, I don't know what code is the cause of the problem. That means I have two choices: 1) offer the entire thing (9 XS files and 4 CPP files), or 2) offer nothing.

      I'm currently tracking down how the items variable is set, to see if that will help me figure out the problem. If that fails, I will start stripping things out of my XS in order to create a single, simple XS file that reproduces the problem, so I will have a saner amount of code to provide.

        I don't know what code is the cause of the problem.

        Historically, I've been reasonably adept at using debuggers, but despite many attempts with several different debuggers, I find tracing into Perl with a debugger pointless. The nature of the run-loop dispatching means that stack traces are nearly always useless, and setting break & watch points an exercise in futility.

        The most effective tool I have found for tracking down segfaults in XS code is printf. I most frequently use the following macro to track down the source of problems:

        #define TAG printf( "# %s(%d)\n", __FILE__, __LINE__ )

        I start by adding TAG;s at the top and bottom of each routine. The last enter tells me which routine to concentrate on. Then I tag strategic points in the routine:

        SV *mapAt( SV *fileMap, U32 hiOff, U32 loOff, size_t size ) { SV *map = newSVpvn( "", 0 ); void *mapAddr; size_t n; TAG; printf( "received size: %I64d\n", size ); ERR( mapAddr = MapViewOfFile( (HANDLE)SvUV( fileMap ), FILE_MAP_ALL_ACCESS, hiOff, loOff, size )); TAG; if( ! size ) { // Mapping entire file MEMORY_BASIC_INFORMATION mi; ERR( VirtualQuery( mapAddr, &mi, sizeof( MEMORY_BASIC_INFORMAT +ION ) ) ); size = mi.RegionSize; printf( "Actual size mapped: %I64u\n", size ); } TAG; SvPV_set( map, mapAddr ); SvCUR_set( map, size ); SvLEN_set( map, size+1 ); TAG; return map; }

        Ideally, the macro would use fprintf( stderr,...), but using stderr within XS code under Windows blows up in horrible ways. (Due to PerlIOs layers of redefinitions of CRT entities in incompatible ways.)

        It is simplistic, but it works. Once you know where your code is failing, working out why is usually not too difficult.

        I also have editor macros to insert and remove the tags on the current line, but that just a nice to have.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        Rip subroutines out of the XS and replace them with Perl dummies. You can even do that without changing your Perl code:

        use My::XS::Module; *My::XS::Module::xs_subroutine_1 = sub { # a dummy }; *My::XS::Module::xs_subroutine_2 = sub { return 0; # always OK };

        That way, you can reduce the complexity as long as you have a test case that reproduces the error.

        My personal guess, without seeing code, is that somewhere you don't POP enough elements of the argument stack, or have a mismatched ENTER / LEAVE pair.