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 <string.h>
00029 #include <signal.h>
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <unistd.h>
00033 #include "kcrash.h"
00034
00035 #include <sys/types.h>
00036 #include <sys/time.h>
00037 #include <sys/resource.h>
00038 #include <sys/wait.h>
00039
00040 #include <qwindowdefs.h>
00041 #include <kglobal.h>
00042 #include <kinstance.h>
00043 #include <kaboutdata.h>
00044 #include <kdebug.h>
00045 #include <kapplication.h>
00046 #include <dcopclient.h>
00047
00048 #ifdef Q_WS_X11
00049 #include <X11/Xlib.h>
00050 #endif
00051
00052 KCrash::HandlerType KCrash::_emergencySaveFunction = 0;
00053 KCrash::HandlerType KCrash::_crashHandler = 0;
00054 const char *KCrash::appName = 0;
00055 const char *KCrash::appPath = 0;
00056
00057
00058
00059
00060 void
00061 KCrash::setEmergencySaveFunction (HandlerType saveFunction)
00062 {
00063 _emergencySaveFunction = saveFunction;
00064
00065
00066
00067
00068
00069 if (_emergencySaveFunction && !_crashHandler)
00070 _crashHandler = defaultCrashHandler;
00071 }
00072
00073
00074
00075
00076 void
00077 KCrash::setCrashHandler (HandlerType handler)
00078 {
00079 if (!handler)
00080 handler = SIG_DFL;
00081
00082 sigset_t mask;
00083 sigemptyset(&mask);
00084
00085 #ifdef SIGSEGV
00086 signal (SIGSEGV, handler);
00087 sigaddset(&mask, SIGSEGV);
00088 #endif
00089 #ifdef SIGFPE
00090 signal (SIGFPE, handler);
00091 sigaddset(&mask, SIGFPE);
00092 #endif
00093 #ifdef SIGILL
00094 signal (SIGILL, handler);
00095 sigaddset(&mask, SIGILL);
00096 #endif
00097 #ifdef SIGABRT
00098 signal (SIGABRT, handler);
00099 sigaddset(&mask, SIGABRT);
00100 #endif
00101
00102 sigprocmask(SIG_UNBLOCK, &mask, 0);
00103
00104 _crashHandler = handler;
00105 }
00106
00107 void
00108 KCrash::defaultCrashHandler (int sig)
00109 {
00110
00111
00112 static int crashRecursionCounter = 0;
00113 crashRecursionCounter++;
00114
00115 signal(SIGALRM, SIG_DFL);
00116 alarm(3);
00117
00118 if (crashRecursionCounter < 2) {
00119 if (_emergencySaveFunction) {
00120 _emergencySaveFunction (sig);
00121 }
00122 crashRecursionCounter++;
00123 }
00124
00125
00126 DCOPClient::emergencyClose();
00127
00128 struct rlimit rlp;
00129 getrlimit(RLIMIT_NOFILE, &rlp);
00130 for (int i = 0; i < (int)rlp.rlim_cur; i++)
00131 close(i);
00132
00133 if (crashRecursionCounter < 3)
00134 {
00135 if (appName)
00136 {
00137 #ifndef NDEBUG
00138 fprintf(stderr, "KCrash: crashing... crashRecursionCounter = %d\n", crashRecursionCounter);
00139 fprintf(stderr, "KCrash: Application Name = %s path = %s pid = %d\n", appName ? appName : "<unknown>" , appPath ? appPath : "<unknown>", getpid());
00140 #else
00141 fprintf(stderr, "KCrash: Application '%s' crashing...\n", appName ? appName : "<unknown>");
00142 #endif
00143
00144 pid_t pid = fork();
00145
00146 if (pid <= 0) {
00147
00148
00149 char * argv[18];
00150 int i = 0;
00151
00152
00153 argv[i++] = qstrdup("drkonqi");
00154
00155
00156 argv[i++] = qstrdup("-display");
00157 #ifdef Q_WS_X11
00158 if ( qt_xdisplay() )
00159 argv[i++] = XDisplayString(qt_xdisplay());
00160 else
00161 argv[i++] = getenv("DISPLAY");
00162 #elif defined(Q_WS_QWS)
00163 argv[i++] = getenv("QWS_DISPLAY");
00164 #endif
00165
00166
00167 argv[i++] = qstrdup("--appname");
00168 argv[i++] = qstrdup(appName);
00169 if (KApplication::loadedByKdeinit)
00170 argv[i++] = qstrdup("--kdeinit");
00171
00172
00173 if (appPath) {
00174 argv[i++] = qstrdup("--apppath");
00175 argv[i++] = qstrdup(appPath);
00176 }
00177
00178
00179 QCString tmp;
00180 tmp.setNum(sig);
00181 argv[i++] = qstrdup("--signal");
00182 argv[i++] = qstrdup(tmp.data());
00183
00184
00185
00186 if (pid == 0) {
00187 tmp.setNum(getppid());
00188 argv[i++] = qstrdup("--pid");
00189 argv[i++] = qstrdup(tmp.data());
00190 }
00191
00192 const KInstance *instance = KGlobal::_instance;
00193 const KAboutData *about = instance ? instance->aboutData() : 0;
00194 if (about) {
00195 if (!about->version().isNull()) {
00196 argv[i++] = qstrdup("--appversion");
00197 argv[i++] = qstrdup(about->version().utf8());
00198 }
00199
00200 if (!about->programName().isNull()) {
00201 argv[i++] = qstrdup("--programname");
00202 argv[i++] = qstrdup(about->programName().utf8());
00203 }
00204
00205 if (!about->bugAddress().isNull()) {
00206 argv[i++] = qstrdup("--bugaddress");
00207 argv[i++] = qstrdup(about->bugAddress().utf8());
00208 }
00209 }
00210
00211 if ( kapp && !kapp->startupId().isNull()) {
00212 argv[i++] = qstrdup("--startupid");
00213 argv[i++] = qstrdup(kapp->startupId());
00214 }
00215
00216
00217 argv[i++] = NULL;
00218
00219 setgid(getgid());
00220 setuid(getuid());
00221
00222 execvp("drkonqi", argv);
00223
00224
00225
00226
00227
00228 }
00229 else
00230 {
00231
00232 alarm(0);
00233
00234
00235 waitpid(pid, NULL, 0);
00236 _exit(253);
00237 }
00238 }
00239 else {
00240 fprintf(stderr, "Unknown appname\n");
00241 }
00242 }
00243
00244 if (crashRecursionCounter < 4)
00245 {
00246 fprintf(stderr, "Unable to start Dr. Konqi\n");
00247 }
00248 _exit(255);
00249 }
This file is part of the documentation for kdelibs Version 3.1.4.