kdecore Library API Documentation

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 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:03:28 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003