diff --git a/kdecore/kcrash.cpp b/kdecore/kcrash.cpp index 2860bc1c9b..23423b6c30 100644 --- a/kdecore/kcrash.cpp +++ b/kdecore/kcrash.cpp @@ -1,225 +1,233 @@ /* * This file is part of the KDE Libraries * Copyright (C) 2000 Timo Hummel * Tom Braun * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * This file is used to catch signals which would normally * crash the application (like segmentation fault, floating * point exception and such). */ #include #include #include #include #include #include "kcrash.h" #include +#include +#include #include #include #include #include #include #include #include #include #ifdef Q_WS_X11 #include #endif KCrash::HandlerType KCrash::_emergencySaveFunction = 0; KCrash::HandlerType KCrash::_crashHandler = 0; const char *KCrash::appName = 0; const char *KCrash::appPath = 0; // This function sets the function which should be called when the // application crashes and the // application is asked to try to save its data. void KCrash::setEmergencySaveFunction (HandlerType saveFunction) { _emergencySaveFunction = saveFunction; /* * We need at least the default crash handler for * emergencySaveFunction to be called */ if (_emergencySaveFunction && !_crashHandler) _crashHandler = defaultCrashHandler; } // This function sets the function which should be responsible for // the application crash handling. void KCrash::setCrashHandler (HandlerType handler) { if (!handler) handler = SIG_DFL; sigset_t mask; sigemptyset(&mask); #ifdef SIGSEGV signal (SIGSEGV, handler); sigaddset(&mask, SIGSEGV); #endif #ifdef SIGFPE signal (SIGFPE, handler); sigaddset(&mask, SIGFPE); #endif #ifdef SIGILL signal (SIGILL, handler); sigaddset(&mask, SIGILL); #endif #ifdef SIGABRT signal (SIGABRT, handler); sigaddset(&mask, SIGABRT); #endif sigprocmask(SIG_UNBLOCK, &mask, 0); _crashHandler = handler; } void KCrash::defaultCrashHandler (int signal) { // WABA: Do NOT use kdDebug() in this function because it is much too risky! // Handle possible recursions static int crashRecursionCounter = 0; crashRecursionCounter++; // Nothing before this, please ! if (crashRecursionCounter < 2) { if (_emergencySaveFunction) { _emergencySaveFunction (signal); } crashRecursionCounter++; // } if (crashRecursionCounter < 3) { if (appName) { fprintf(stderr, "KCrash: crashing.... crashRecursionCounter = %d\n", crashRecursionCounter); fprintf(stderr, "KCrash: Application Name = %s path = %s pid = %d\n", appName ? appName : "" , appPath ? appPath : "", getpid()); pid_t pid = fork(); if (pid <= 0) { // this code is leaking, but this should not hurt cause we will do a // exec() afterwards. exec() is supposed to clean up. char * argv[16]; // don't forget to update this int i = 0; // argument 0 has to be drkonqi argv[i++] = qstrdup("drkonqi"); // start up on the correct display argv[i++] = qstrdup("-display"); #ifdef Q_WS_X11 if ( qt_xdisplay() ) argv[i++] = XDisplayString(qt_xdisplay()); else argv[i++] = getenv("DISPLAY"); #elif defined(Q_WS_QWS) argv[i++] = getenv("QWS_DISPLAY"); #endif // we have already tested this argv[i++] = qstrdup("--appname"); argv[i++] = qstrdup(appName); if (KApplication::loadedByKdeinit) argv[i++] = qstrdup("--kdeinit"); // only add apppath if it's not NULL if (appPath) { argv[i++] = qstrdup("--apppath"); argv[i++] = qstrdup(appPath); } // signal number -- will never be NULL QCString tmp; tmp.setNum(signal); argv[i++] = qstrdup("--signal"); argv[i++] = qstrdup(tmp.data()); // pid number -- only include if this is the child // the debug stuff will be disabled if we was not able to fork if (pid == 0) { tmp.setNum(getppid()); argv[i++] = qstrdup("--pid"); argv[i++] = qstrdup(tmp.data()); } const KInstance *instance = KGlobal::_instance; const KAboutData *about = instance ? instance->aboutData() : 0; if (about) { if (!about->version().isNull()) { argv[i++] = qstrdup("--appversion"); argv[i++] = qstrdup(about->version().utf8()); } if (!about->programName().isNull()) { argv[i++] = qstrdup("--programname"); argv[i++] = qstrdup(about->programName().utf8()); } if (!about->bugAddress().isNull()) { argv[i++] = qstrdup("--bugaddress"); argv[i++] = qstrdup(about->bugAddress().utf8()); } } // NULL terminated list argv[i++] = NULL; setgid(getgid()); setuid(getuid()); execvp("drkonqi", argv); // we could clean up here // i = 0; // while (argv[i]) // free(argv[i++]); } else { // Close dcop connections DCOPClient::emergencyClose(); + // Close all remaining file descriptors + struct rlimit rlp; + getrlimit(RLIMIT_NOFILE, &rlp); + for (int i = 0; i < (int)rlp.rlim_cur; i++) + close(i); + // wait for child to exit waitpid(pid, NULL, 0); _exit(253); } } else { fprintf(stderr, "Unknown appname\n"); } } if (crashRecursionCounter < 4) { fprintf(stderr, "Unable to start dr. konqi\n"); } _exit(255); }