kdecore Library: kcrash.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kcrash.cpp

    00001 /*
    00002  * This file is part of the KDE Libraries
    00003  * Copyright (C) 2000 Timo Hummel <timo.hummel@sap.com>
    00004  *                    Tom Braun <braunt@fh-konstanz.de>
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the GNU Library General Public
    00008  * License as published by the Free Software Foundation; either
    00009  * version 2 of the License, or (at your option) any later version.
    00010  *
    00011  * This library is distributed in the hope that it will be useful,
    00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00014  * Library General Public License for more details.
    00015  *
    00016  * You should have received a copy of the GNU Library General Public License
    00017  * along with this library; see the file COPYING.LIB.  If not, write to
    00018  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00019  * Boston, MA 02111-1307, USA.
    00020  */
    00021
    00022 /*
    00023  * This file is used to catch signals which would normally
    00024  * crash the application (like segmentation fault, floating
    00025  * point exception and such).
    00026  */
    00027
    00028 #include "config.h"
    00029
    00030 #include <string.h>
    00031 #include <signal.h>
    00032 #include <stdio.h>
    00033 #include <stdlib.h>
    00034 #include <unistd.h>
    00035 #include "kcrash.h"
    00036
    00037 #include <sys/types.h>
    00038 #include <sys/time.h>
    00039 #include <sys/resource.h>
    00040 #include <sys/wait.h>
    00041
    00042 #include <qwindowdefs.h>
    00043 #include <kglobal.h>
    00044 #include <kinstance.h>
    00045 #include <kaboutdata.h>
    00046 #include <kdebug.h>
    00047 #include <kapplication.h>
    00048 #include <dcopclient.h>
    00049
    00050 #if defined Q_WS_X11
    00051 #include <X11/Xlib.h>
    00052 #endif
    00053
    00054 KCrash::HandlerType KCrash::_emergencySaveFunction = 0;
    00055 KCrash::HandlerType KCrash::_crashHandler = 0;
    00056 const char *KCrash::appName = 0;
    00057 const char *KCrash::appPath = 0;
    00058 bool KCrash::safer = false;
    00059
    00060 // This function sets the function which should be called when the
    00061 // application crashes and the
    00062 // application is asked to try to save its data.
    00063 void
    00064 KCrash::setEmergencySaveFunction (HandlerType saveFunction)
    00065 {
    00066   _emergencySaveFunction = saveFunction;
    00067
    00068   /*
    00069    * We need at least the default crash handler for
    00070    * emergencySaveFunction to be called
    00071    */
    00072   if (_emergencySaveFunction && !_crashHandler)
    00073     _crashHandler = defaultCrashHandler;
    00074 }
    00075
    00076
    00077 // This function sets the function which should be responsible for
    00078 // the application crash handling.
    00079 void
    00080 KCrash::setCrashHandler (HandlerType handler)
    00081 {
    00082 #ifdef Q_OS_UNIX
    00083   if (!handler)
    00084     handler = SIG_DFL;
    00085
    00086   sigset_t mask;
    00087   sigemptyset(&mask);
    00088
    00089 #ifdef SIGSEGV
    00090   signal (SIGSEGV, handler);
    00091   sigaddset(&mask, SIGSEGV);
    00092 #endif
    00093 #ifdef SIGFPE
    00094   signal (SIGFPE, handler);
    00095   sigaddset(&mask, SIGFPE);
    00096 #endif
    00097 #ifdef SIGILL
    00098   signal (SIGILL, handler);
    00099   sigaddset(&mask, SIGILL);
    00100 #endif
    00101 #ifdef SIGABRT
    00102   signal (SIGABRT, handler);
    00103   sigaddset(&mask, SIGABRT);
    00104 #endif
    00105
    00106   sigprocmask(SIG_UNBLOCK, &mask, 0);
    00107 #endif //Q_OS_UNIX
    00108
    00109   _crashHandler = handler;
    00110 }
    00111
    00112 void
    00113 KCrash::defaultCrashHandler (int sig)
    00114 {
    00115 #ifdef Q_OS_UNIX
    00116   // WABA: Do NOT use kdDebug() in this function because it is much too risky!
    00117   // Handle possible recursions
    00118   static int crashRecursionCounter = 0;
    00119   crashRecursionCounter++; // Nothing before this, please !
    00120
    00121   signal(SIGALRM, SIG_DFL);
    00122   alarm(3); // Kill me... (in case we deadlock in malloc)
    00123
    00124   if (crashRecursionCounter < 2) {
    00125     if (_emergencySaveFunction) {
    00126       _emergencySaveFunction (sig);
    00127     }
    00128     crashRecursionCounter++; //
    00129   }
    00130
    00131         // Close dcop connections
    00132   DCOPClient::emergencyClose();
    00133   // Close all remaining file descriptors except for stdin/stdout/stderr
    00134   struct rlimit rlp;
    00135   getrlimit(RLIMIT_NOFILE, &rlp);
    00136   for (int i = 3; i < (int)rlp.rlim_cur; i++)
    00137     close(i);
    00138
    00139   bool shuttingDown = false;
    00140
    00141   // don't load drkonqi during shutdown
    00142   if ( !shuttingDown )
    00143   {
    00144     if (crashRecursionCounter < 3)
    00145     {
    00146       if (appName)
    00147       {
    00148 #ifndef NDEBUG
    00149         fprintf(stderr, "KCrash: crashing... crashRecursionCounter = %d\n", crashRecursionCounter);
    00150         fprintf(stderr, "KCrash: Application Name = %s path = %s pid = %d\n", appName ? appName : "<unknown>" , appPath ? appPath : "<unknown>", getpid());
    00151 #else
    00152         fprintf(stderr, "KCrash: Application '%s' crashing...\n", appName ? appName : "<unknown>");
    00153 #endif
    00154
    00155         pid_t pid = fork();
    00156
    00157         if (pid <= 0) {
    00158           // this code is leaking, but this should not hurt cause we will do a
    00159           // exec() afterwards. exec() is supposed to clean up.
    00160           char * argv[24]; // don't forget to update this
    00161           int i = 0;
    00162
    00163           // argument 0 has to be drkonqi
    00164           argv[i++] = qstrdup("drkonqi");
    00165
    00166 #if defined Q_WS_X11
    00167           // start up on the correct display
    00168           argv[i++] = qstrdup("-display");
    00169           if ( qt_xdisplay() )
    00170             argv[i++] = XDisplayString(qt_xdisplay());
    00171           else
    00172             argv[i++] = getenv("DISPLAY");
    00173 #elif defined(Q_WS_QWS)
    00174           // start up on the correct display
    00175           argv[i++] = qstrdup("-display");
    00176           argv[i++] = getenv("QWS_DISPLAY");
    00177 #endif
    00178
    00179           // we have already tested this
    00180           argv[i++] = qstrdup("--appname");
    00181           argv[i++] = qstrdup(appName);
    00182           if (KApplication::loadedByKdeinit)
    00183             argv[i++] = qstrdup("--kdeinit");
    00184
    00185           // only add apppath if it's not NULL
    00186           if (appPath) {
    00187             argv[i++] = qstrdup("--apppath");
    00188             argv[i++] = qstrdup(appPath);
    00189           }
    00190
    00191           // signal number -- will never be NULL
    00192           QCString tmp;
    00193           tmp.setNum(sig);
    00194           argv[i++] = qstrdup("--signal");
    00195           argv[i++] = qstrdup(tmp.data());
    00196
    00197           // pid number -- only include if this is the child
    00198           // the debug stuff will be disabled if we was not able to fork
    00199           if (pid == 0) {
    00200             tmp.setNum(getppid());
    00201             argv[i++] = qstrdup("--pid");
    00202             argv[i++] = qstrdup(tmp.data());
    00203           }
    00204
    00205           const KInstance *instance = KGlobal::_instance;
    00206           const KAboutData *about = instance ? instance->aboutData() : 0;
    00207           if (about) {
    00208             if (!about->version().isNull()) {
    00209               argv[i++] = qstrdup("--appversion");
    00210               argv[i++] = qstrdup(about->version().utf8());
    00211             }
    00212
    00213             if (!about->programName().isNull()) {
    00214               argv[i++] = qstrdup("--programname");
    00215               argv[i++] = qstrdup(about->programName().utf8());
    00216             }
    00217
    00218             if (!about->bugAddress().isNull()) {
    00219               argv[i++] = qstrdup("--bugaddress");
    00220               argv[i++] = qstrdup(about->bugAddress().utf8());
    00221             }
    00222           }
    00223
    00224           if ( kapp && !kapp->startupId().isNull()) {
    00225             argv[i++] = qstrdup("--startupid");
    00226             argv[i++] = qstrdup(kapp->startupId());
    00227           }
    00228
    00229           if ( safer )
    00230             argv[i++] = qstrdup("--safer");
    00231
    00232           // NULL terminated list
    00233           argv[i++] = NULL;
    00234
    00235           setgid(getgid());
    00236           setuid(getuid());
    00237
    00238           execvp("drkonqi", argv);
    00239
    00240           // we could clean up here
    00241           // i = 0;
    00242           // while (argv[i])
    00243           //   free(argv[i++]);
    00244         }
    00245         else
    00246         {
    00247
    00248           alarm(0); // Seems we made it....
    00249
    00250           // wait for child to exit
    00251           waitpid(pid, NULL, 0);
    00252           _exit(253);
    00253         }
    00254       }
    00255       else {
    00256         fprintf(stderr, "Unknown appname\n");
    00257       }
    00258     }
    00259
    00260     if (crashRecursionCounter < 4)
    00261     {
    00262       fprintf(stderr, "Unable to start Dr. Konqi\n");
    00263     }
    00264   }
    00265 #endif //Q_OS_UNIX
    00266
    00267   _exit(255);
    00268 }

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:03 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003