Devel-bt
view release on metacpan or search on metacpan
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifndef PERL_UNUSED_ARG
# define PERL_UNUSED_ARG(x) ((void)x)
#endif
static int signals[] = {
SIGILL,
SIGFPE,
SIGBUS,
SIGSEGV,
SIGTRAP,
SIGABRT,
SIGQUIT
};
static char perl_path[PATH_MAX], gdb_path[PATH_MAX];
static void
register_sighandler (void (*handler)(int))
{
unsigned int i;
for (i = 0; i < sizeof(signals) / sizeof(signals[0]); i++) {
signal(signals[i], handler);
}
}
static void
stack_trace (char **args)
{
pid_t pid;
int in_fd[2], out_fd[2], idx, state;
fd_set fdset;
char buffer[4096];
/* stop gdb from wrapping lines */
snprintf(buffer, sizeof(buffer), "%u", (unsigned int)sizeof(buffer));
setenv("COLUMNS", buffer, 1);
if ((pipe(in_fd) == -1) || (pipe(out_fd) == -1)) {
perror("unable to open pipe");
_exit(0);
}
pid = fork();
if (pid == 0) {
/* double fork+_exit so we can properly detach from the parent
process. this is important because some platforms (only OpenBSD for
now) don't allow ptrace()ing their parent processes, which is what we
need to be able to do to have a working gdb. */
pid = fork();
if (pid == 0) {
char buf[16];
/* just to be sure the kernel doesn't recognize us as an inferiour
process */
if (setsid() == (pid_t)-1) {
perror("setsid failed");
_exit(0);
}
close(0); dup(in_fd[0]);
close(1); dup(out_fd[1]);
close(2); dup(out_fd[1]);
snprintf(buf, sizeof(buf), "%u\n", getpid());
write(1, buf, strlen(buf));
execvp(args[0], args);
perror("exec failed");
_exit(0);
}
else if (pid == (pid_t)-1) {
perror("unable to fork");
_exit(0);
}
else {
_exit(0);
}
}
else if (pid == (pid_t)-1) {
perror("unable to fork");
_exit(0);
}
FD_ZERO(&fdset);
FD_SET(out_fd[0], &fdset);
write(in_fd[1], "thread apply all backtrace\n", 27);
write(in_fd[1], "quit\n", 5);
idx = 0;
state = 0;
while (1) {
pid_t gdb_pid;
struct timeval tv;
int sel;
( run in 1.143 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )