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
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 #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
00117
00118 static int crashRecursionCounter = 0;
00119 crashRecursionCounter++;
00120
00121 signal(SIGALRM, SIG_DFL);
00122 alarm(3);
00123
00124 if (crashRecursionCounter < 2) {
00125 if (_emergencySaveFunction) {
00126 _emergencySaveFunction (sig);
00127 }
00128 crashRecursionCounter++;
00129 }
00130
00131
00132 DCOPClient::emergencyClose();
00133
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
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
00159
00160 char * argv[24];
00161 int i = 0;
00162
00163
00164 argv[i++] = qstrdup("drkonqi");
00165
00166 #if defined Q_WS_X11
00167
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
00175 argv[i++] = qstrdup("-display");
00176 argv[i++] = getenv("QWS_DISPLAY");
00177 #endif
00178
00179
00180 argv[i++] = qstrdup("--appname");
00181 argv[i++] = qstrdup(appName);
00182 if (KApplication::loadedByKdeinit)
00183 argv[i++] = qstrdup("--kdeinit");
00184
00185
00186 if (appPath) {
00187 argv[i++] = qstrdup("--apppath");
00188 argv[i++] = qstrdup(appPath);
00189 }
00190
00191
00192 QCString tmp;
00193 tmp.setNum(sig);
00194 argv[i++] = qstrdup("--signal");
00195 argv[i++] = qstrdup(tmp.data());
00196
00197
00198
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
00233 argv[i++] = NULL;
00234
00235 setgid(getgid());
00236 setuid(getuid());
00237
00238 execvp("drkonqi", argv);
00239
00240
00241
00242
00243
00244 }
00245 else
00246 {
00247
00248 alarm(0);
00249
00250
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.