Discussion:
How to get stack info in XS die handler
(too old to reply)
Tom
2008-06-05 12:21:50 UTC
Permalink
How will I find ou where the problem occured inside a die handler in
XS? Something like call stack when the exception occured. Thanks TT
Marvin Humphrey
2008-06-05 15:49:48 UTC
Permalink
Post by Tom
How will I find ou where the problem occured inside a die handler in
XS? Something like call stack when the exception occured.
I got the Perl stack into error messages by wrapping a callback to
Carp::confess(). In a perfect world we'd get the C stack in there
too, but oh well.

If you want portability, you have to special case things depending on
whether variadic macros are available. Assuming that they are, in ISO-
style, and also that the ISO-style __func__ macro is available, this
works:

#define CONFESS(...) \
confess_at(__FILE__, __LINE__, __func__, __VA_ARGS__)

void
confess_at(const char *file, int line, const char *func,
const char *pat, ...)
{
va_list args;
SV *error_sv = newSVpvf("Error in function %s at %s:%d: ", func,
file, line);

va_start(args, pat);
sv_vcatpvf(error_sv, pat, &args);
va_end(args);

sv_catpvn(error_sv, "\n\t", 2);

do_confess(error_sv);
}

void
do_confess(SV *error_sv)
{
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal(error_sv) );
PUTBACK;
call_pv("Carp::confess", G_DISCARD);
FREETMPS;
LEAVE;
}

Marvin Humphrey
Rectangular Research
http://www.rectangular.com/
Tom
2008-06-06 10:55:27 UTC
Permalink
Post by Tom
How will I find ou where the problem occured inside a die handler in
XS? Something like call stack when the exception occured.
I got the Perl stack into error messages by wrapping a callback to  
Carp::confess().  In a perfect world we'd get the C stack in there  
too, but oh well.
If you want portability, you have to special case things depending on  
whether variadic macros are available. Assuming that they are, in ISO-
style, and also that the ISO-style __func__ macro is available, this  
#define CONFESS(...) \
     confess_at(__FILE__, __LINE__, __func__, __VA_ARGS__)
void
confess_at(const char *file, int line, const char *func,
            const char *pat, ...)
{
     va_list args;
     SV *error_sv = newSVpvf("Error in function %s at %s:%d: ", func,
         file, line);
     va_start(args, pat);
     sv_vcatpvf(error_sv, pat, &args);
     va_end(args);
     sv_catpvn(error_sv, "\n\t", 2);
     do_confess(error_sv);
}
void
do_confess(SV *error_sv)
{
     dSP;
     ENTER;
     SAVETMPS;
     PUSHMARK(SP);
     XPUSHs( sv_2mortal(error_sv) );
     PUTBACK;
     call_pv("Carp::confess", G_DISCARD);
     FREETMPS;
     LEAVE;
}
Marvin Humphrey
Rectangular Researchhttp://www.rectangular.com/
Thanks for that. But that is not what I am looking for really. I
already have a die handler which traps any perl errors. I would like
to access the stack trace from that C code and write it to log.

I was thinking if I can access any of the perl variables from there.
Or using eval (eval_pv), and caller(). But not getting anywhere. I am
new to Perl !

Loading...