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 = 3; 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 }