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 }