[Spice-devel] [PATCH v2] common: add backtrace via gstack or glibc backtrace

Alon Levy alevy at redhat.com
Mon Jul 18 08:42:14 PDT 2011


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.
---
 common/Makefile.am    |    2 +
 common/backtrace.c    |  114 +++++++++++++++++++++++++++++++++++++++++++++++++
 common/backtrace.h    |   24 ++++++++++
 common/spice_common.h |    2 +
 configure.ac          |    1 +
 5 files changed, 143 insertions(+), 0 deletions(-)
 create mode 100644 common/backtrace.c
 create mode 100644 common/backtrace.h

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();                                                \
 }
 
diff --git a/configure.ac b/configure.ac
index c058edd..3268df6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,6 +27,7 @@ AC_C_BIGENDIAN
 AC_PATH_PROGS(PYTHON, python2 python)
 
 AC_CHECK_HEADERS([sys/time.h])
+AC_CHECK_HEADERS([execinfo.h])
 AC_FUNC_ALLOCA
 
 SPICE_LT_VERSION=m4_format("%d:%d:%d", 1, 0, 2)
-- 
1.7.6



More information about the Spice-devel mailing list