diff options
author | Alon Levy <alevy@redhat.com> | 2011-07-14 10:50:49 +0300 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@gmail.com> | 2012-03-20 15:25:53 +0100 |
commit | cb4c660655cb3f1f82598a4424049552de431d52 (patch) | |
tree | aae498c0eb662a891ef65f3c21b4c1a8f6186ff2 | |
parent | da4768ae2b36df3acf650e95eb9d17bbf201bb8e (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-- | common/Makefile.am | 2 | ||||
-rw-r--r-- | common/backtrace.c | 114 | ||||
-rw-r--r-- | common/backtrace.h | 24 | ||||
-rw-r--r-- | common/spice_common.h | 2 |
4 files changed, 142 insertions, 0 deletions
diff --git a/common/Makefile.am b/common/Makefile.am index e0f4d49..f07f948 100644 --- a/common/Makefile.am +++ b/common/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/common/backtrace.c b/common/backtrace.c new file mode 100644 index 0000000..d606dd9 --- /dev/null +++ b/common/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/common/backtrace.h b/common/backtrace.h new file mode 100644 index 0000000..3b0c132 --- /dev/null +++ b/common/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/common/spice_common.h b/common/spice_common.h index bc74486..6c5154c 100644 --- a/common/spice_common.h +++ b/common/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(); \ } |