38 #include <sys/types.h>
40 #include <sys/resource.h>
43 #include <sys/socket.h>
46 #include <tqwindowdefs.h>
47 #include <tdeglobal.h>
48 #include <kinstance.h>
49 #include <tdeaboutdata.h>
51 #include <tdeapplication.h>
52 #include <dcopclient.h>
54 #include <../tdeinit/tdelauncher_cmds.h>
62 const char *TDECrash::appName = 0;
63 const char *TDECrash::appPath = 0;
64 bool TDECrash::safer =
false;
96 signal (SIGSEGV, handler);
97 sigaddset(&mask, SIGSEGV);
100 signal (SIGFPE, handler);
101 sigaddset(&mask, SIGFPE);
104 signal (SIGILL, handler);
105 sigaddset(&mask, SIGILL);
108 signal (SIGABRT, handler);
109 sigaddset(&mask, SIGABRT);
112 sigprocmask(SIG_UNBLOCK, &mask, 0);
124 static int crashRecursionCounter = 0;
125 crashRecursionCounter++;
127 signal(SIGALRM, SIG_DFL);
130 if (crashRecursionCounter < 2) {
134 crashRecursionCounter++;
139 getrlimit(RLIMIT_NOFILE, &rlp);
140 for (
int i = 3; i < (int)rlp.rlim_cur; i++)
146 if (crashRecursionCounter < 3)
151 fprintf(stderr,
"[kcrash] TDECrash: crashing... crashRecursionCounter = %d\n", crashRecursionCounter);
152 fprintf(stderr,
"[kcrash] TDECrash: Application Name = %s path = %s pid = %d\n", appName ? appName :
"<unknown>" , appPath ? appPath :
"<unknown>", getpid());
154 fprintf(stderr,
"[kcrash] TDECrash: Application '%s' crashing...\n", appName ? appName :
"<unknown>");
157 const char * argv[24];
161 argv[i++] =
"drkonqi";
163 #if defined TQ_WS_X11
165 argv[i++] =
"-display";
166 if ( tqt_xdisplay() )
167 argv[i++] = XDisplayString(tqt_xdisplay());
169 argv[i++] = getenv(
"DISPLAY");
170 #elif defined(TQ_WS_QWS)
172 argv[i++] =
"-display";
173 argv[i++] = getenv(
"QWS_DISPLAY");
177 argv[i++] =
"--appname";
179 if (TDEApplication::loadedByKdeinit)
180 argv[i++] =
"--tdeinit";
184 argv[i++] =
"--apppath";
190 sprintf( sigtxt,
"%d", sig );
191 argv[i++] =
"--signal";
195 sprintf( pidtxt,
"%d", getpid());
199 const TDEInstance *instance = TDEGlobal::_instance;
202 if (about->internalVersion()) {
203 argv[i++] =
"--appversion";
204 argv[i++] = about->internalVersion();
207 if (about->internalProgramName()) {
208 argv[i++] =
"--programname";
209 argv[i++] = about->internalProgramName();
212 if (about->internalBugAddress()) {
213 argv[i++] =
"--bugaddress";
214 argv[i++] = about->internalBugAddress();
218 if ( kapp && !kapp->startupId().isNull()) {
219 argv[i++] =
"--startupid";
220 argv[i++] = kapp->startupId().data();
224 argv[i++] =
"--safer";
229 startDrKonqi( argv, i );
234 fprintf(stderr,
"[kcrash] Unknown appname\n");
238 if (crashRecursionCounter < 4)
240 fprintf(stderr,
"[kcrash] Unable to start Dr. Konqi\n");
253 static int write_socket(
int sock,
char *buffer,
int len);
254 static int read_socket(
int sock,
char *buffer,
int len);
255 static int openSocket();
257 void TDECrash::startDrKonqi(
const char* argv[],
int argc )
259 int socket = openSocket();
262 startDirectly( argv, argc );
265 tdelauncher_header header;
266 header.cmd = LAUNCHER_EXEC_NEW;
267 const int BUFSIZE = 8192;
268 char buffer[ BUFSIZE + 10 ];
271 memcpy( buffer + pos, &argcl,
sizeof( argcl ));
272 pos +=
sizeof( argcl );
277 int len = strlen( argv[ i ] ) + 1;
278 if( pos + len > BUFSIZE )
280 fprintf( stderr,
"[kcrash] BUFSIZE in TDECrash not big enough!\n" );
281 startDirectly( argv, argc );
284 memcpy( buffer + pos, argv[ i ], len );
288 memcpy( buffer + pos, &env,
sizeof( env ));
289 pos +=
sizeof( env );
290 long avoid_loops = 0;
291 memcpy( buffer + pos, &avoid_loops,
sizeof( avoid_loops ));
292 pos +=
sizeof( avoid_loops );
293 header.arg_length = pos;
294 write_socket(socket, (
char *) &header,
sizeof(header));
295 write_socket(socket, buffer, pos);
296 if( read_socket( socket, (
char *) &header,
sizeof(header)) < 0
297 || header.cmd != LAUNCHER_OK )
299 startDirectly( argv, argc );
303 read_socket(socket, buffer, header.arg_length);
304 pid = *((
long *) buffer);
310 if( kill( pid, 0 ) < 0 )
318 void TDECrash::startDirectly(
const char* argv[],
int )
320 fprintf( stderr,
"[kcrash] TDECrash cannot reach tdeinit, launching directly.\n" );
324 if(!geteuid() && setgid(getgid()) < 0)
326 if(!geteuid() && setuid(getuid()) < 0)
328 execvp(
"drkonqi",
const_cast< char**
>( argv ));
335 waitpid(pid, NULL, 0);
342 extern char **environ;
344 static char *getDisplay()
359 display = getenv(
"DISPLAY");
361 display = getenv(
"QWS_DISPLAY");
363 if (!display || !*display)
367 result = (
char*)malloc(strlen(display)+1);
371 strcpy(result, display);
372 screen = strrchr(result,
'.');
373 colon = strrchr(result,
':');
374 if (screen && (screen > colon))
376 while((i = strchr(result,
':')))
385 static int write_socket(
int sock,
char *buffer,
int len)
388 int bytes_left = len;
389 while ( bytes_left > 0)
391 result = write(sock, buffer, bytes_left);
395 bytes_left -= result;
397 else if (result == 0)
399 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
409 static int read_socket(
int sock,
char *buffer,
int len)
412 int bytes_left = len;
413 while ( bytes_left > 0)
415 result = read(sock, buffer, bytes_left);
419 bytes_left -= result;
421 else if (result == 0)
423 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
429 static int openSocket()
431 kde_socklen_t socklen;
433 struct sockaddr_un server;
434 #define MAX_SOCK_FILE 255
435 char sock_file[MAX_SOCK_FILE + 1];
436 const char *home_dir = getenv(
"HOME");
437 const char *kde_home = getenv(
"TDEHOME");
440 sock_file[0] = sock_file[MAX_SOCK_FILE] = 0;
442 if (!kde_home || !kde_home[0])
444 kde_home =
"~/.trinity/";
447 if (kde_home[0] ==
'~')
449 if (!home_dir || !home_dir[0])
451 fprintf(stderr,
"[kcrash] Warning: $HOME not set!\n");
454 if (strlen(home_dir) > (MAX_SOCK_FILE-100))
456 fprintf(stderr,
"[kcrash] Warning: Home directory path too long!\n");
460 strncpy(sock_file, home_dir, MAX_SOCK_FILE);
462 strncat(sock_file, kde_home, MAX_SOCK_FILE - strlen(sock_file));
465 if ( sock_file[strlen(sock_file)-1] ==
'/')
466 sock_file[strlen(sock_file)-1] = 0;
468 strncat(sock_file,
"/socket-", MAX_SOCK_FILE - strlen(sock_file));
469 if( getenv(
"XAUTHLOCALHOSTNAME"))
470 strncat(sock_file, getenv(
"XAUTHLOCALHOSTNAME"), MAX_SOCK_FILE - strlen(sock_file) - 1);
471 else if (gethostname(sock_file+strlen(sock_file), MAX_SOCK_FILE - strlen(sock_file) - 1) != 0)
473 perror(
"[kcrash] Warning: Could not determine hostname: ");
476 sock_file[
sizeof(sock_file)-1] =
'\0';
479 display = getDisplay();
482 fprintf(stderr,
"[kcrash] Error: Could not determine display.\n");
486 if (strlen(sock_file)+strlen(display)+strlen(
"/tdeinit_")+2 > MAX_SOCK_FILE)
488 fprintf(stderr,
"[kcrash] Warning: Socket name will be too long.\n");
492 strcat(sock_file,
"/tdeinit_");
493 strcat(sock_file, display);
496 if (strlen(sock_file) >=
sizeof(server.sun_path))
498 fprintf(stderr,
"[kcrash] Warning: Path of socketfile exceeds UNIX_PATH_MAX.\n");
505 s = socket(PF_UNIX, SOCK_STREAM, 0);
508 perror(
"[kcrash] Warning: socket creation failed: ");
512 server.sun_family = AF_UNIX;
513 strcpy(server.sun_path, sock_file);
514 socklen =
sizeof(server);
515 if(connect(s, (
struct sockaddr *)&server, socklen) == -1)
517 perror(
"[kcrash] Warning: socket connection failed: ");
This class is used to store information about a program.
static HandlerType _crashHandler
Pointer to the crash handler.
void(* HandlerType)(int)
This function type is a pointer to a crash handler function.
static void setEmergencySaveFunction(HandlerType saveFunction=(HandlerType) 0)
Installs a function which should try to save the applications data.
static void defaultCrashHandler(int signal)
The default crash handler.
static HandlerType _emergencySaveFunction
Pointer to the emergency save function.
static void setCrashHandler(HandlerType handler=defaultCrashHandler)
Install a function to be called in case a SIGSEGV is caught.
Access to KDE global objects for use in shared libraries.
const TDEAboutData * aboutData() const
Returns the about data of this instance Warning, can be 0L.
TDEAction * close(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)