diff options
Diffstat (limited to 'src/corelib/kernel/qcrashhandler.cpp')
-rw-r--r-- | src/corelib/kernel/qcrashhandler.cpp | 421 |
1 files changed, 0 insertions, 421 deletions
diff --git a/src/corelib/kernel/qcrashhandler.cpp b/src/corelib/kernel/qcrashhandler.cpp deleted file mode 100644 index 46bb8b7c11..0000000000 --- a/src/corelib/kernel/qcrashhandler.cpp +++ /dev/null @@ -1,421 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/************************************************************************* - * - * stacktrace.c 1.2 1998/12/21 - * - * Copyright (c) 1998 by Bjorn Reese <breese@imada.ou.dk> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -#include "qplatformdefs.h" -#include "private/qcrashhandler_p.h" -#include "qbytearray.h" // for qvsnprintf() - -#ifndef QT_NO_CRASHHANDLER - -#include <stdio.h> -#include <signal.h> -#include <stdlib.h> - -QT_BEGIN_NAMESPACE - -QtCrashHandler QSegfaultHandler::callback = 0; - -#if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE) -QT_BEGIN_INCLUDE_NAMESPACE -# include "qstring.h" -# include <execinfo.h> -QT_END_INCLUDE_NAMESPACE - -static void print_backtrace(FILE *outb) -{ - void *stack[128]; - int stack_size = backtrace(stack, sizeof(stack) / sizeof(void *)); - char **stack_symbols = backtrace_symbols(stack, stack_size); - fprintf(outb, "Stack [%d]:\n", stack_size); - if(FILE *cppfilt = popen("c++filt", "rw")) { - dup2(fileno(outb), fileno(cppfilt)); - for(int i = stack_size-1; i>=0; --i) - fwrite(stack_symbols[i], 1, strlen(stack_symbols[i]), cppfilt); - pclose(cppfilt); - } else { - for(int i = stack_size-1; i>=0; --i) - fprintf(outb, "#%d %p [%s]\n", i, stack[i], stack_symbols[i]); - } -} -static void init_backtrace(char **, int) -{ -} - -#else /* Don't use the GLIBC callback */ -/* Code sourced from: */ -QT_BEGIN_INCLUDE_NAMESPACE -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/wait.h> -#if defined(Q_OS_IRIX) && defined(USE_LIBEXC) -# include <libexc.h> -#endif -QT_END_INCLUDE_NAMESPACE - - -static char *globalProgName = NULL; -static bool backtrace_command(FILE *outb, const char *format, ...) -{ - - bool ret = false; - char buffer[50]; - - /* - * Please note that vsnprintf() is not ASync safe (ie. cannot safely - * be used from a signal handler.) If this proves to be a problem - * then the cmd string can be built by more basic functions such as - * strcpy, strcat, and a home-made integer-to-ascii function. - */ - va_list args; - char cmd[512]; - va_start(args, format); - qvsnprintf(cmd, 512, format, args); - va_end(args); - - char *foo = cmd; -#if 0 - foo = "echo hi"; -#endif - if(FILE *inb = popen(foo, "r")) { - while(!feof(inb)) { - int len = fread(buffer, 1, sizeof(buffer), inb); - if(!len) - break; - if(!ret) { - fwrite("Output from ", 1, strlen("Output from "), outb); - strtok(cmd, " "); - fwrite(cmd, 1, strlen(cmd), outb); - fwrite("\n", 1, 1, outb); - ret = true; - } - fwrite(buffer, 1, len, outb); - } - fclose(inb); - } - return ret; -} - -static void init_backtrace(char **argv, int argc) -{ - if(argc >= 1) - globalProgName = argv[0]; -} - -static void print_backtrace(FILE *outb) -{ - /* - * In general dbx seems to do a better job than gdb. - * - * Different dbx implementations require different flags/commands. - */ -#if defined(Q_OS_AIX) - if(backtrace_command(outb, "dbx -a %d 2>/dev/null <<EOF\n" - "where\n" - "detach\n" - "EOF\n", - (int)getpid())) - return; - if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n" - "set prompt\n" - "where\n" - "detach\n" - "quit\n" - "EOF\n", - globalProgName, (int)getpid())) - return; -#elif defined(Q_OS_FREEBSD) - /* - * FreeBSD insists on sending a SIGSTOP to the process we - * attach to, so we let the debugger send a SIGCONT to that - * process after we have detached. - */ - if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n" - "set prompt\n" - "where\n" - "detach\n" - "shell kill -CONT %d\n" - "quit\n" - "EOF\n", - globalProgName, (int)getpid(), (int)getpid())) - return; -#elif defined(Q_OS_HPUX) - /* - * HP decided to call their debugger xdb. - * - * This does not seem to work properly yet. The debugger says - * "Note: Stack traces may not be possible until you are - * stopped in user code." on HP-UX 09.01 - * - * -L = line-oriented interface. - * "T [depth]" gives a stacktrace with local variables. - * The final "y" is confirmation to the quit command. - */ - if(backtrace_command(outb, "xdb -P %d -L %s 2>&1 <<EOF\n" - "T 50\n" - "q\ny\n" - "EOF\n", - (int)getpid(), globalProgName)) - return; - if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n" - "set prompt\n" - "where\n" - "detach\n" - "quit\n" - "EOF\n", - globalProgName, (int)getpid())) - return; -#elif defined(Q_OS_IRIX) - /* - * "set $page=0" drops hold mode - * "dump ." displays the contents of the variables - */ - if(backtrace_command(outb, "dbx -p %d 2>/dev/null <<EOF\n" - "set \\$page=0\n" - "where\n" -# if !defined(__GNUC__) - /* gcc does not generate this information */ - "dump .\n" -# endif - "detach\n" - "EOF\n", - (int)getpid())) - return; - -# if defined(USE_LIBEXC) - if(trace_back_stack_and_print()) - return; -# endif - if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n" - "set prompt\n" - "where\n" - "echo ---\\n\n" - "frame 5\n" /* Skip signal handler frames */ - "set \\$x = 50\n" - "while (\\$x)\n" /* Print local variables for each frame */ - "info locals\n" - "up\n" - "set \\$x--\n" - "end\n" - "echo ---\\n\n" - "detach\n" - "quit\n" - "EOF\n", - globalProgName, (int)getpid())) - return; -#elif defined(Q_OS_OSF) - if(backtrace_command(outb, "dbx -pid %d %s 2>/dev/null <<EOF\n" - "where\n" - "detach\n" - "quit\n" - "EOF\n", - (int)getpid(), globalProgName)) - return; - if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n" - "set prompt\n" - "where\n" - "detach\n" - "quit\n" - "EOF\n", - globalProgName, (int)getpid())) - return; -#elif defined(Q_OS_SCO) - /* - * SCO OpenServer dbx is like a catch-22. The 'detach' command - * depends on whether ptrace(S) support detaching or not. If it - * is supported then 'detach' must be used, otherwise the process - * will be killed upon dbx exit. If it isn't supported then 'detach' - * will cause the process to be killed. We do not want it to be - * killed. - * - * Out of two evils, the omission of 'detach' was chosen because - * it worked on our system. - */ - if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n" - "where\n" - "quit\nEOF\n", - globalProgName, (int)getpid())) - return; - if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n" - "set prompt\n" - "where\n" - "detach\n" - "quit\n" - "EOF\n", - globalProgName, (int)getpid())) - return; -#elif defined(Q_OS_SOLARIS) - if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n" - "where\n" - "detach\n" - "EOF\n", - globalProgName, (int)getpid())) - return; - if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n" - "set prompt\n" - "where\n" - "echo ---\\n\n" - "frame 5\n" /* Skip signal handler frames */ - "set \\$x = 50\n" - "while (\\$x)\n" /* Print local variables for each frame */ - "info locals\n" - "up\n" - "set \\$x--\n" - "end\n" - "echo ---\\n\n" - "detach\n" - "quit\n" - "EOF\n", - globalProgName, (int)getpid())) - return; - if(backtrace_command(outb, "/usr/proc/bin/pstack %d", - (int)getpid())) - return; - /* - * Other Unices (AIX, HPUX, SCO) also have adb, but - * they seem unable to attach to a running process.) - */ - if(backtrace_command(outb, "adb %s 2>&1 <<EOF\n" - "0t%d:A\n" /* Attach to pid */ - "\\$c\n" /* print stacktrace */ - ":R\n" /* Detach */ - "\\$q\n" /* Quit */ - "EOF\n", - globalProgName, (int)getpid())) - return; -#elif defined(Q_OS_INTEGRITY) - /* abort */ - CheckSuccess(Failure); -#else /* All other platforms */ - /* - * TODO: SCO/UnixWare 7 must be something like (not tested) - * debug -i c <pid> <<EOF\nstack -f 4\nquit\nEOF\n - */ -# if !defined(__GNUC__) - if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n" - "where\n" - "detach\n" - "EOF\n", - globalProgName, (int)getpid())) - return; -# endif - if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n" - "set prompt\n" - "where\n" -#if 0 - "echo ---\\n\n" - "frame 4\n" - "set \\$x = 50\n" - "while (\\$x)\n" - "info locals\n" - "up\n" - "set \\$x--\n" - "end\n" - "echo ---\\n\n" -#endif - "detach\n" - "quit\n" - "EOF\n", - globalProgName, (int)getpid())) - return; -#endif - const char debug_err[] = "No debugger found\n"; - fwrite(debug_err, strlen(debug_err), 1, outb); -} -/* end of copied code */ -#endif - - -void qt_signal_handler(int sig) -{ - signal(sig, SIG_DFL); - if(QSegfaultHandler::callback) { - (*QSegfaultHandler::callback)(); - _exit(1); - } - FILE *outb = stderr; - if(char *crash_loc = ::getenv("QT_CRASH_OUTPUT")) { - if(FILE *new_outb = fopen(crash_loc, "w")) { - fprintf(stderr, "Crash (backtrace written to %s)!!!\n", crash_loc); - outb = new_outb; - } - } else { - fprintf(outb, "Crash!!!\n"); - } - print_backtrace(outb); - if(outb != stderr) - fclose(outb); - _exit(1); -} - - -void -QSegfaultHandler::initialize(char **argv, int argc) -{ - init_backtrace(argv, argc); - - struct sigaction SignalAction; - SignalAction.sa_flags = 0; - SignalAction.sa_handler = qt_signal_handler; - sigemptyset(&SignalAction.sa_mask); - sigaction(SIGSEGV, &SignalAction, NULL); - sigaction(SIGBUS, &SignalAction, NULL); -} - -QT_END_NAMESPACE - -#endif // QT_NO_CRASHHANDLER |