diff options
author | Alon Levy <alevy@redhat.com> | 2011-07-14 10:50:49 +0300 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2011-07-19 20:33:25 +0300 |
commit | 3aff246075dd95ad5e298f49d98a34570c8a6f86 (patch) | |
tree | 34bf1950c7a7a989ff3bde11d8154701742e9dcc | |
parent | 8365513b12c3a8c25871ca1bc9b626194d1983d5 (diff) |
common: add backtrace via gstack or glibc backtrace
Add a backtrace printing function copied from xserver os/backtrace.c
that uses gstack, and if that isn't found then glibc's backtrace.
Used in ASSERT, tested on F15.
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | backtrace.c | 114 | ||||
-rw-r--r-- | backtrace.h | 24 | ||||
-rw-r--r-- | spice_common.h | 2 |
4 files changed, 142 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index e0f4d49..f07f948 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,6 +36,8 @@ libspice_common_la_SOURCES = \ spice_common.h \ ssl_verify.c \ ssl_verify.h \ + backtrace.c \ + backtrace.h \ $(NULL) if SUPPORT_GL diff --git a/backtrace.c b/backtrace.c new file mode 100644 index 0000000..d606dd9 --- /dev/null +++ b/backtrace.c @@ -0,0 +1,114 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Taken from xserver os/backtrace.c: + * Copyright 2008 Red Hat, Inc. + */ + +#include "config.h" +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> +#include "common/spice_common.h" + +#define GSTACK_PATH "/usr/bin/gstack" + +#if HAVE_EXECINFO_H +#include <execinfo.h> + +static void spice_backtrace_backtrace(void) +{ + void *array[100]; + int size; + + size = backtrace(array, sizeof(array)/sizeof(array[0])); + backtrace_symbols_fd(array, size, STDERR_FILENO); +} +#else +static void spice_backtrace_backtrace(void) +{ +} +#endif + +static int spice_backtrace_gstack(void) +{ + pid_t kidpid; + int pipefd[2]; + + if (pipe(pipefd) != 0) { + return -1; + } + + kidpid = fork(); + + if (kidpid == -1) { + /* ERROR */ + return -1; + } else if (kidpid == 0) { + /* CHILD */ + char parent[16]; + + seteuid(0); + close(STDIN_FILENO); + close(STDOUT_FILENO); + dup2(pipefd[1],STDOUT_FILENO); + close(STDERR_FILENO); + + snprintf(parent, sizeof(parent), "%d", getppid()); + execle(GSTACK_PATH, "gstack", parent, NULL, NULL); + exit(1); + } else { + /* PARENT */ + char btline[256]; + int kidstat; + int bytesread; + int done = 0; + + close(pipefd[1]); + + while (!done) { + bytesread = read(pipefd[0], btline, sizeof(btline) - 1); + + if (bytesread > 0) { + btline[bytesread] = 0; + fprintf(stderr, "%s", btline); + } + else if ((bytesread == 0) || + ((errno != EINTR) && (errno != EAGAIN))) { + done = 1; + } + } + close(pipefd[0]); + waitpid(kidpid, &kidstat, 0); + if (kidstat != 0) + return -1; + } + return 0; +} + +void spice_backtrace() { + if (!access(GSTACK_PATH, X_OK)) { + spice_backtrace_gstack(); + } else { + spice_backtrace_backtrace(); + } +} diff --git a/backtrace.h b/backtrace.h new file mode 100644 index 0000000..3b0c132 --- /dev/null +++ b/backtrace.h @@ -0,0 +1,24 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2011 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef BACKTRACE_H +#define BACKTRACE_H + +void spice_backtrace(void); + +#endif // BACKTRACE_H diff --git a/spice_common.h b/spice_common.h index bc74486..6c5154c 100644 --- a/spice_common.h +++ b/spice_common.h @@ -22,9 +22,11 @@ #include <stdint.h> #include <time.h> #include <stdlib.h> +#include "backtrace.h" #define ASSERT(x) if (!(x)) { \ printf("%s: ASSERT %s failed\n", __FUNCTION__, #x); \ + spice_backtrace(); \ abort(); \ } |