kcrash.cpp
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
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 && ! defined K_WS_QTONLY
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 
00061 
00062 
00063 void
00064 KCrash::setEmergencySaveFunction (HandlerType saveFunction)
00065 {
00066   _emergencySaveFunction = saveFunction;
00067 
00068   
00069 
00070 
00071 
00072   if (_emergencySaveFunction && !_crashHandler)
00073     _crashHandler = defaultCrashHandler;
00074 }
00075 
00076 
00077 
00078 
00079 void
00080 KCrash::setCrashHandler (HandlerType handler)
00081 {
00082   if (!handler)
00083     handler = SIG_DFL;
00084 
00085   sigset_t mask;
00086   sigemptyset(&mask);
00087 
00088 #ifdef SIGSEGV
00089   signal (SIGSEGV, handler);
00090   sigaddset(&mask, SIGSEGV);
00091 #endif
00092 #ifdef SIGFPE
00093   signal (SIGFPE, handler);
00094   sigaddset(&mask, SIGFPE);
00095 #endif
00096 #ifdef SIGILL
00097   signal (SIGILL, handler);
00098   sigaddset(&mask, SIGILL);
00099 #endif
00100 #ifdef SIGABRT
00101   signal (SIGABRT, handler);
00102   sigaddset(&mask, SIGABRT);
00103 #endif
00104 
00105   sigprocmask(SIG_UNBLOCK, &mask, 0);
00106 
00107   _crashHandler = handler;
00108 }
00109 
00110 void
00111 KCrash::defaultCrashHandler (int sig)
00112 {
00113   
00114   
00115   static int crashRecursionCounter = 0;
00116   crashRecursionCounter++; 
00117 
00118   signal(SIGALRM, SIG_DFL);
00119   alarm(3); 
00120 
00121   if (crashRecursionCounter < 2) {
00122     if (_emergencySaveFunction) {
00123       _emergencySaveFunction (sig);
00124     }
00125     crashRecursionCounter++; 
00126   }
00127 
00128         
00129   DCOPClient::emergencyClose();
00130   
00131   struct rlimit rlp;
00132   getrlimit(RLIMIT_NOFILE, &rlp);
00133   for (int i = 0; i < (int)rlp.rlim_cur; i++)
00134     close(i);
00135 
00136   bool shuttingDown = false;
00137 
00138   
00139   if ( !shuttingDown )
00140   {
00141     if (crashRecursionCounter < 3)
00142     {
00143       if (appName)
00144       {
00145 #ifndef NDEBUG
00146         fprintf(stderr, "KCrash: crashing... crashRecursionCounter = %d\n", crashRecursionCounter);
00147         fprintf(stderr, "KCrash: Application Name = %s path = %s pid = %d\n", appName ? appName : "<unknown>" , appPath ? appPath : "<unknown>", getpid());
00148 #else
00149         fprintf(stderr, "KCrash: Application '%s' crashing...\n", appName ? appName : "<unknown>");
00150 #endif
00151 
00152         pid_t pid = fork();
00153 
00154         if (pid <= 0) {
00155           
00156           
00157           char * argv[24]; 
00158           int i = 0;
00159 
00160           
00161           argv[i++] = qstrdup("drkonqi");
00162 
00163           
00164           argv[i++] = qstrdup("-display");
00165 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00166           if ( qt_xdisplay() )
00167             argv[i++] = XDisplayString(qt_xdisplay());
00168           else
00169             argv[i++] = getenv("DISPLAY");
00170 #elif defined(Q_WS_QWS)
00171           argv[i++] = getenv("QWS_DISPLAY");
00172 #endif
00173 
00174           
00175           argv[i++] = qstrdup("--appname");
00176           argv[i++] = qstrdup(appName);
00177           if (KApplication::loadedByKdeinit)
00178             argv[i++] = qstrdup("--kdeinit");
00179 
00180           
00181           if (appPath) {
00182             argv[i++] = qstrdup("--apppath");
00183             argv[i++] = qstrdup(appPath);
00184           }
00185 
00186           
00187           QCString tmp;
00188           tmp.setNum(sig);
00189           argv[i++] = qstrdup("--signal");
00190           argv[i++] = qstrdup(tmp.data());
00191 
00192           
00193           
00194           if (pid == 0) {
00195             tmp.setNum(getppid());
00196             argv[i++] = qstrdup("--pid");
00197             argv[i++] = qstrdup(tmp.data());
00198           }
00199 
00200           const KInstance *instance = KGlobal::_instance;
00201           const KAboutData *about = instance ? instance->aboutData() : 0;
00202           if (about) {
00203             if (!about->version().isNull()) {
00204               argv[i++] = qstrdup("--appversion");
00205               argv[i++] = qstrdup(about->version().utf8());
00206             }
00207 
00208             if (!about->programName().isNull()) {
00209               argv[i++] = qstrdup("--programname");
00210               argv[i++] = qstrdup(about->programName().utf8());
00211             }
00212 
00213             if (!about->bugAddress().isNull()) {
00214               argv[i++] = qstrdup("--bugaddress");
00215               argv[i++] = qstrdup(about->bugAddress().utf8());
00216             }
00217           }
00218 
00219           if ( kapp && !kapp->startupId().isNull()) {
00220             argv[i++] = qstrdup("--startupid");
00221             argv[i++] = qstrdup(kapp->startupId());
00222           }
00223 
00224           if ( safer )
00225             argv[i++] = qstrdup("--safer");
00226 
00227           
00228           argv[i++] = NULL;
00229 
00230           setgid(getgid());
00231           setuid(getuid());
00232 
00233           execvp("drkonqi", argv);
00234 
00235           
00236           
00237           
00238           
00239         }
00240         else
00241         {
00242 
00243           alarm(0); 
00244 
00245           
00246           waitpid(pid, NULL, 0);
00247           _exit(253);
00248         }
00249       }
00250       else {
00251         fprintf(stderr, "Unknown appname\n");
00252       }
00253     }
00254 
00255     if (crashRecursionCounter < 4)
00256     {
00257       fprintf(stderr, "Unable to start Dr. Konqi\n");
00258     }
00259   }
00260 
00261   _exit(255);
00262 }
 
This file is part of the documentation for kdecore Library Version 3.2.0.