• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • util
kcrash.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the KDE Libraries
3 * Copyright (C) 2000 Timo Hummel <timo.hummel@sap.com>
4 * Tom Braun <braunt@fh-konstanz.de>
5 * Copyright 2009 KDE e.V.
6 * By Adriaan de Groot <groot@kde.org>
7 * Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25#include "kcrash.h"
26#include <kcmdlineargs.h>
27#include <kstandarddirs.h>
28#include <config-kstandarddirs.h>
29
30#include <config.h>
31
32#include <string.h>
33#include <signal.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <unistd.h>
37
38#include <sys/types.h>
39#include <sys/time.h>
40#include <sys/resource.h>
41#include <sys/wait.h>
42#include <sys/un.h>
43#include <sys/socket.h>
44#ifdef Q_OS_LINUX
45#include <sys/prctl.h>
46#endif
47#include <errno.h>
48
49#include <qwindowdefs.h>
50#include <kglobal.h>
51#include <kcomponentdata.h>
52#include <kaboutdata.h>
53#include <kdebug.h>
54#include <kapplication.h>
55
56#include <../kinit/klauncher_cmds.h>
57
58#include <QtCore/QFileInfo>
59#include <QtCore/QDir>
60
61#if defined Q_WS_X11
62#include <qx11info_x11.h>
63#include <X11/Xlib.h>
64#endif
65
66#ifdef Q_OS_SOLARIS
67// Solaris has built-in, thread-safe, async-signal-safe, mechanisms
68// to walk the stack in the case of a crash, as well as (optionally)
69// to demangle C++ symbol names. In the case of a crash, dump a stack
70// trace to stderr before starting drKonqui (because what drKonqui is
71// going to do is -- through a complicated process -- print the
72// exact same information, but less reliably).
73#include <ucontext.h>
74#endif
75
76#if defined(Q_OS_WIN)
77# include <windows.h>
78#endif
79
80static KCrash::HandlerType s_emergencySaveFunction = 0;
81static KCrash::HandlerType s_crashHandler = 0;
82static char *s_appName = 0;
83static char *s_autoRestartCommand = 0;
84static char *s_appPath = 0;
85static int s_autoRestartArgc = 0;
86static char **s_autoRestartCommandLine = 0;
87static char *s_drkonqiPath = 0;
88static KCrash::CrashFlags s_flags = 0;
89static bool s_launchDrKonqi = false;
90
91namespace KCrash
92{
93 void startProcess(int argc, const char *argv[], bool waitAndExit);
94
95#if defined(Q_OS_WIN)
96 LONG WINAPI win32UnhandledExceptionFilter(_EXCEPTION_POINTERS *exceptionInfo);
97#endif
98}
99
100void
101KCrash::setEmergencySaveFunction (HandlerType saveFunction)
102{
103 s_emergencySaveFunction = saveFunction;
104
105 /*
106 * We need at least the default crash handler for
107 * emergencySaveFunction to be called
108 */
109 if (s_emergencySaveFunction && !s_crashHandler) {
110 setCrashHandler(defaultCrashHandler);
111 }
112}
113
114KCrash::HandlerType
115KCrash::emergencySaveFunction()
116{
117 return s_emergencySaveFunction;
118}
119
120// Set the default crash handler in 10 seconds
121// This is used after an autorestart, the second instance of the application
122// is started with --nocrashhandler (no drkonqi, more precisely), and we
123// set the defaultCrashHandler (to handle autorestart) after 10s.
124// The delay is to see if we stay up for more than 10s time, to avoid infinite
125// respawning if the app crashes on startup.
126class KCrashDelaySetHandler : public QObject
127{
128public:
129 KCrashDelaySetHandler() {
130 startTimer(10000); // 10 s
131 }
132protected:
133 void timerEvent(QTimerEvent *event) {
134 if (!s_crashHandler) // not set meanwhile
135 KCrash::setCrashHandler(KCrash::defaultCrashHandler);
136 killTimer(event->timerId());
137 this->deleteLater();
138 }
139};
140
141
142
143void
144KCrash::setFlags(KCrash::CrashFlags flags)
145{
146 s_flags = flags;
147 if (s_flags & AutoRestart) {
148 // We need at least the default crash handler for autorestart to work.
149 if (!s_crashHandler) {
150 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
151 if (!args->isSet("crashhandler")) // --nocrashhandler was passed, probably due to a crash, delay restart handler
152 new KCrashDelaySetHandler;
153 else // probably because KDE_DEBUG=1. set restart handler immediately.
154 setCrashHandler(defaultCrashHandler);
155 }
156 }
157}
158
159//### KDE5:Consider merging the setApplicationPath and setApplicationName methods into one.
160void
161KCrash::setApplicationPath(const QString& path)
162{
163 s_appPath = qstrdup(QFile::encodeName(path).constData());
164
165 //if the appName has also been specified, update s_autoRestartCommand to be in the form "absolutePath/appName"
166 if (s_appName) {
167 delete[] s_autoRestartCommand;
168 QFileInfo appExecutable(QDir(path), QFile::decodeName(s_appName));
169 QByteArray cmd = QFile::encodeName(appExecutable.absoluteFilePath());
170 s_autoRestartCommand = qstrdup(cmd.constData());
171 }
172
173 QStringList args = KCmdLineArgs::allArguments();
174 args[0] = s_autoRestartCommand; // replace argv[0] with full path above
175 if (!args.contains("--nocrashhandler"))
176 args.insert(1, "--nocrashhandler");
177 delete[] s_autoRestartCommandLine;
178 s_autoRestartArgc = args.count();
179 s_autoRestartCommandLine = new char* [args.count() + 1];
180 for (int i = 0; i < args.count(); ++i) {
181 s_autoRestartCommandLine[i] = qstrdup(QFile::encodeName(args.at(i)).constData());
182 }
183 s_autoRestartCommandLine[args.count()] = 0;
184}
185
186void
187KCrash::setApplicationName(const QString& name)
188{
189 s_appName = qstrdup(QFile::encodeName(name).constData());
190
191 //update the autoRestartCommand
192 delete[] s_autoRestartCommand;
193 if (s_appPath) {
194 //if we have appPath, make autoRestartCommand be in the form "absolutePath/appName"...
195 QFileInfo appExecutable(QDir(QFile::decodeName(s_appPath)), name);
196 QByteArray cmd = QFile::encodeName(appExecutable.absoluteFilePath());
197 s_autoRestartCommand = qstrdup(cmd.constData());
198 } else {
199 //...else just use the appName for the autoRestartCommand
200 s_autoRestartCommand = qstrdup(s_appName);
201 }
202}
203
204void KCrash::setDrKonqiEnabled(bool enabled)
205{
206 s_launchDrKonqi = enabled;
207 if (s_launchDrKonqi && !s_drkonqiPath) {
208
209 s_drkonqiPath = qstrdup(QFile::encodeName(KStandardDirs::findExe("drkonqi", QFile::decodeName("/usr/libexec/drkonqi"))).constData());
210
211 if (!s_drkonqiPath) {
212
213 s_drkonqiPath = qstrdup(QFile::encodeName(KStandardDirs::findExe("drkonqi")).constData());
214 if (!s_drkonqiPath) {
215 kError() << "Could not find drkonqi";
216 s_launchDrKonqi = false;
217 }
218
219 }
220 }
221
222 //we need at least the default crash handler to launch drkonqi
223 if (s_launchDrKonqi && !s_crashHandler) {
224 setCrashHandler(defaultCrashHandler);
225 }
226}
227
228bool KCrash::isDrKonqiEnabled()
229{
230 return s_launchDrKonqi;
231}
232
233void
234KCrash::setCrashHandler (HandlerType handler)
235{
236#if defined(Q_OS_WIN)
237 static LPTOP_LEVEL_EXCEPTION_FILTER s_previousExceptionFilter = NULL;
238
239 if (handler && !s_previousExceptionFilter) {
240 s_previousExceptionFilter = SetUnhandledExceptionFilter(KCrash::win32UnhandledExceptionFilter);
241 } else if (!handler && s_previousExceptionFilter) {
242 SetUnhandledExceptionFilter(s_previousExceptionFilter);
243 s_previousExceptionFilter = NULL;
244 }
245#else
246 if (!handler)
247 handler = SIG_DFL;
248
249 sigset_t mask;
250 sigemptyset(&mask);
251
252#ifdef SIGSEGV
253 signal (SIGSEGV, handler);
254 sigaddset(&mask, SIGSEGV);
255#endif
256#ifdef SIGBUS
257 signal (SIGBUS, handler);
258 sigaddset(&mask, SIGBUS);
259#endif
260#ifdef SIGFPE
261 signal (SIGFPE, handler);
262 sigaddset(&mask, SIGFPE);
263#endif
264#ifdef SIGILL
265 signal (SIGILL, handler);
266 sigaddset(&mask, SIGILL);
267#endif
268#ifdef SIGABRT
269 signal (SIGABRT, handler);
270 sigaddset(&mask, SIGABRT);
271#endif
272
273 sigprocmask(SIG_UNBLOCK, &mask, 0);
274#endif
275
276 s_crashHandler = handler;
277}
278
279KCrash::HandlerType
280KCrash::crashHandler()
281{
282 return s_crashHandler;
283}
284
285static void
286closeAllFDs()
287{
288 // Close all remaining file descriptors except for stdin/stdout/stderr
289 struct rlimit rlp;
290 getrlimit(RLIMIT_NOFILE, &rlp);
291 for (int i = 3; i < (int)rlp.rlim_cur; i++)
292 close(i);
293}
294
295void
296KCrash::defaultCrashHandler (int sig)
297{
298 // WABA: Do NOT use kDebug() in this function because it is much too risky!
299 // Handle possible recursions
300 static int crashRecursionCounter = 0;
301 crashRecursionCounter++; // Nothing before this, please !
302
303#if !defined(Q_OS_WIN)
304 signal(SIGALRM, SIG_DFL);
305 alarm(3); // Kill me... (in case we deadlock in malloc)
306#endif
307
308#ifdef Q_OS_SOLARIS
309 (void) printstack(2 /* stderr, assuming it's still open. */);
310#endif
311
312 if (crashRecursionCounter < 2) {
313 if (s_emergencySaveFunction) {
314 s_emergencySaveFunction (sig);
315 }
316 if ((s_flags & AutoRestart) && s_autoRestartCommand) {
317 sleep(1);
318 startProcess(s_autoRestartArgc, const_cast<const char**>(s_autoRestartCommandLine), false);
319 }
320 crashRecursionCounter++;
321 }
322
323 // On Apple OS X, closing all FDs now will cause a second (SIGILL) crash,
324 // ending with "Unable to start Dr. Konqi". This is because the libdispatch
325 // library, which can manage multi-threading, has some FDs of its own.
326 //
327 // Note: KCrash closes FDs unconditionally later on if it forks to Dr Konqi
328 // and this program's FDs do not matter if kdeinit starts Dr Konqi.
329#if !defined(Q_OS_WIN) and !defined(Q_OS_MAC)
330 if (!(s_flags & KeepFDs))
331 closeAllFDs();
332# if defined(Q_WS_X11)
333 else if (QX11Info::display())
334 close(ConnectionNumber(QX11Info::display()));
335# endif
336#endif
337
338 if (crashRecursionCounter < 3)
339 {
340#ifndef NDEBUG
341 fprintf(stderr, "KCrash: crashing... crashRecursionCounter = %d\n",
342 crashRecursionCounter);
343 fprintf(stderr, "KCrash: Application Name = %s path = %s pid = %lld\n",
344 s_appName ? s_appName : "<unknown>" ,
345 s_appPath ? s_appPath : "<unknown>", QCoreApplication::applicationPid());
346 fprintf(stderr, "KCrash: Arguments: ");
347 for (int i = 0; s_autoRestartCommandLine[i]; ++i) {
348 fprintf(stderr, "%s ", s_autoRestartCommandLine[i]);
349 }
350 fprintf(stderr, "\n");
351#else
352 fprintf(stderr, "KCrash: Application '%s' crashing...\n",
353 s_appName ? s_appName : "<unknown>");
354#endif
355
356 if (!s_launchDrKonqi) {
357 setCrashHandler(0);
358#if !defined(Q_OS_WIN)
359 raise(sig); // dump core, or whatever is the default action for this signal.
360#endif
361 return;
362 }
363
364 const char * argv[27]; // don't forget to update this
365 int i = 0;
366
367 // argument 0 has to be drkonqi
368 argv[i++] = s_drkonqiPath;
369
370#if defined Q_WS_X11
371 // start up on the correct display
372 argv[i++] = "-display";
373 if ( QX11Info::display() )
374 argv[i++] = XDisplayString(QX11Info::display());
375 else
376 argv[i++] = getenv("DISPLAY");
377#elif defined(Q_WS_QWS)
378 // start up on the correct display
379 argv[i++] = "-display";
380 argv[i++] = getenv("QWS_DISPLAY");
381#endif
382
383 argv[i++] = "--appname";
384 argv[i++] = s_appName ? s_appName : "<unknown>";
385
386 if (KApplication::loadedByKdeinit)
387 argv[i++] = "--kdeinit";
388
389 // only add apppath if it's not NULL
390 if (s_appPath && *s_appPath) {
391 argv[i++] = "--apppath";
392 argv[i++] = s_appPath;
393 }
394
395 // signal number -- will never be NULL
396 char sigtxt[ 10 ];
397 sprintf( sigtxt, "%d", sig );
398 argv[i++] = "--signal";
399 argv[i++] = sigtxt;
400
401 char pidtxt[ 20 ];
402 sprintf( pidtxt, "%lld", QCoreApplication::applicationPid());
403 argv[i++] = "--pid";
404 argv[i++] = pidtxt;
405
406 const KComponentData componentData = KGlobal::mainComponent();
407 const KAboutData *about = componentData.isValid() ? componentData.aboutData() : 0;
408 if (about) {
409 if (about->internalVersion()) {
410 argv[i++] = "--appversion";
411 argv[i++] = about->internalVersion();
412 }
413
414 if (about->internalProgramName()) {
415 argv[i++] = "--programname";
416 argv[i++] = about->internalProgramName();
417 }
418
419 if (about->internalBugAddress()) {
420 argv[i++] = "--bugaddress";
421 argv[i++] = about->internalBugAddress();
422 }
423 }
424
425 char sidtxt[256];
426 if ( kapp && !kapp->startupId().isNull()) {
427 argv[i++] = "--startupid";
428 strlcpy(sidtxt, kapp->startupId().constData(), sizeof(sidtxt));
429 argv[i++] = sidtxt;
430 }
431
432 if ( s_flags & SaferDialog )
433 argv[i++] = "--safer";
434
435 if ((s_flags & AutoRestart) && s_autoRestartCommand)
436 argv[i++] = "--restarted"; //tell drkonqi if the app has been restarted
437
438#if defined(Q_OS_WIN)
439 char threadId[8] = { 0 };
440 sprintf( threadId, "%d", GetCurrentThreadId() );
441 argv[i++] = "--thread";
442 argv[i++] = threadId;
443#endif
444
445 // NULL terminated list
446 argv[i] = NULL;
447
448 startProcess(i, argv, true);
449 }
450
451 if (crashRecursionCounter < 4)
452 {
453 fprintf(stderr, "Unable to start Dr. Konqi\n");
454 }
455
456 _exit(255);
457}
458
459#if defined(Q_OS_WIN)
460
461void KCrash::startProcess(int argc, const char *argv[], bool waitAndExit)
462{
463 QString cmdLine;
464 for(int i=0; i<argc; ++i) {
465 cmdLine.append('\"');
466 cmdLine.append(QFile::decodeName(argv[i]));
467 cmdLine.append("\" ");
468 }
469
470 PROCESS_INFORMATION procInfo;
471 STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
472 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
473 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
474 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
475
476 bool success = CreateProcess(0, (wchar_t*) cmdLine.utf16(), NULL, NULL,
477 false, CREATE_UNICODE_ENVIRONMENT, NULL, NULL,
478 &startupInfo, &procInfo);
479
480 if (success && waitAndExit) {
481 // wait for child to exit
482 WaitForSingleObject(procInfo.hProcess, INFINITE);
483 _exit(253);
484 }
485}
486
487//glue function for calling the unix signal handler from the windows unhandled exception filter
488LONG WINAPI KCrash::win32UnhandledExceptionFilter(_EXCEPTION_POINTERS *exceptionInfo)
489{
490 // kdbgwin needs the context inside exceptionInfo because if getting the context after the
491 // exception happened, it will walk down the stack and will stop at KiUserEventDispatch in
492 // ntdll.dll, which is supposed to dispatch the exception from kernel mode back to user mode
493 // so... let's create some shared memory
494 HANDLE hMapFile = NULL;
495 hMapFile = CreateFileMapping(
496 INVALID_HANDLE_VALUE,
497 NULL,
498 PAGE_READWRITE,
499 0,
500 sizeof(CONTEXT),
501 TEXT("Local\\KCrashShared"));
502
503 LPCTSTR pBuf = NULL;
504 pBuf = (LPCTSTR) MapViewOfFile(
505 hMapFile,
506 FILE_MAP_ALL_ACCESS,
507 0,
508 0,
509 sizeof(CONTEXT));
510 CopyMemory((PVOID) pBuf, exceptionInfo->ContextRecord, sizeof(CONTEXT));
511
512 if (s_crashHandler) {
513 s_crashHandler(exceptionInfo->ExceptionRecord->ExceptionCode);
514 }
515
516 CloseHandle(hMapFile);
517 return EXCEPTION_EXECUTE_HANDLER; //allow windows to do the default action (terminate)
518}
519#else
520
521static bool startProcessInternal(int argc, const char *argv[], bool waitAndExit, bool directly);
522static pid_t startFromKdeinit(int argc, const char *argv[]);
523static pid_t startDirectly(const char *argv[]);
524static int write_socket(int sock, char *buffer, int len);
525static int read_socket(int sock, char *buffer, int len);
526static int openSocket();
527
528void KCrash::startProcess(int argc, const char *argv[], bool waitAndExit)
529{
530 bool startDirectly = true;
531
532 // First try to start the app via kdeinit, if the AlwaysDirectly flag hasn't been specified.
533 // This is done because it is dangerous to use fork() in the crash handler
534 // (there can be functions registered to be performed before fork(), for example handling
535 // of malloc locking, which doesn't work when malloc crashes because of heap corruption).
536#ifndef Q_OS_MAC
537 // Fails on Apple OSX+KDE4, because kdeinit4 is using the wrong socket name.
538 if (!(s_flags & AlwaysDirectly)) {
539 startDirectly = !startProcessInternal(argc, argv, waitAndExit, false);
540 }
541#endif
542
543 // If we can't reach kdeinit, we can still at least try to fork()
544 if (startDirectly) {
545 startProcessInternal(argc, argv, waitAndExit, true);
546 }
547}
548
549static bool startProcessInternal(int argc, const char *argv[], bool waitAndExit, bool directly)
550{
551 fprintf(stderr, "KCrash: Attempting to start %s %s\n", argv[0], directly ? "directly" : "from kdeinit");
552
553 pid_t pid = directly ? startDirectly(argv) : startFromKdeinit(argc, argv);
554
555 if (pid > 0 && waitAndExit) {
556 // Seems we made it....
557 alarm(0); //stop the pending alarm that was set at the top of the defaultCrashHandler
558
559 // Wait forever until the started process exits. This code path is executed
560 // when launching drkonqi. Note that drkonqi will stop this process in the meantime.
561 if (directly) {
562 //if the process was started directly, use waitpid(), as it's a child...
563 while(waitpid(-1, NULL, 0) != pid) {}
564 } else {
565#ifdef Q_OS_LINUX
566 // Declare the process that will be debugging the crashed KDE app (#245529)
567#ifndef PR_SET_PTRACER
568# define PR_SET_PTRACER 0x59616d61
569#endif
570 prctl(PR_SET_PTRACER, pid, 0, 0, 0);
571#endif
572 //...else poll its status using kill()
573 while(kill(pid, 0) >= 0) {
574 sleep(1);
575 }
576 }
577 _exit(253);
578 }
579
580 return (pid > 0); //return true on success
581}
582
583static pid_t startFromKdeinit(int argc, const char *argv[])
584{
585 int socket = openSocket();
586 if( socket < -1 )
587 return 0;
588 klauncher_header header;
589 header.cmd = LAUNCHER_EXEC_NEW;
590 const int BUFSIZE = 8192; // make sure this is big enough
591 char buffer[ BUFSIZE + 10 ];
592 int pos = 0;
593 long argcl = argc;
594 memcpy( buffer + pos, &argcl, sizeof( argcl ));
595 pos += sizeof( argcl );
596 for( int i = 0;
597 i < argc;
598 ++i )
599 {
600 int len = strlen( argv[ i ] ) + 1; // include terminating \0
601 if( pos + len >= BUFSIZE )
602 {
603 fprintf( stderr, "BUFSIZE in KCrash not big enough!\n" );
604 return 0;
605 }
606 memcpy( buffer + pos, argv[ i ], len );
607 pos += len;
608 }
609 long env = 0;
610 memcpy( buffer + pos, &env, sizeof( env ));
611 pos += sizeof( env );
612 long avoid_loops = 0;
613 memcpy( buffer + pos, &avoid_loops, sizeof( avoid_loops ));
614 pos += sizeof( avoid_loops );
615 header.arg_length = pos;
616 write_socket(socket, (char *) &header, sizeof(header));
617 write_socket(socket, buffer, pos);
618 if( read_socket( socket, (char *) &header, sizeof(header)) < 0
619 || header.cmd != LAUNCHER_OK )
620 {
621 return 0;
622 }
623 long pid;
624 read_socket(socket, (char *) &pid, sizeof(pid));
625 return static_cast<pid_t>(pid);
626}
627
628static pid_t startDirectly(const char *argv[])
629{
630 pid_t pid = fork();
631 switch (pid)
632 {
633 case -1:
634 fprintf( stderr, "KCrash failed to fork(), errno = %d\n", errno );
635 return 0;
636 case 0:
637 if (setgid(getgid()) < 0 || setuid(getuid()) < 0)
638 _exit(253); // This cannot happen. Theoretically.
639 closeAllFDs(); // We are in the child now. Close FDs unconditionally.
640 execvp(argv[0], const_cast< char** >(argv));
641 fprintf( stderr, "KCrash failed to exec(), errno = %d\n", errno );
642 _exit(253);
643 default:
644 return pid;
645 }
646}
647
648// From now on this code is copy&pasted from kinit/wrapper.c :
649
650static char *getDisplay()
651{
652 const char *display;
653 char *result;
654 char *screen;
655 char *colon;
656 char *i;
657/*
658 don't test for a value from qglobal.h but instead distinguish
659 Qt/X11 from Qt/Embedded by the fact that Qt/E apps have -DQWS
660 on the commandline (which in qglobal.h however triggers Q_WS_QWS,
661 but we don't want to include that here) (Simon)
662#ifdef Q_WS_X11
663 */
664#ifdef NO_DISPLAY
665 display = "NODISPLAY";
666#elif !defined(QWS)
667 display = getenv("DISPLAY");
668#else
669 display = getenv("QWS_DISPLAY");
670#endif
671 if (!display || !*display)
672 {
673 display = ":0";
674 }
675 result = (char*)malloc(strlen(display)+1);
676 if (result == NULL)
677 return NULL;
678
679 strcpy(result, display);
680 screen = strrchr(result, '.');
681 colon = strrchr(result, ':');
682 if (screen && (screen > colon))
683 *screen = '\0';
684 while((i = strchr(result, ':')))
685 *i = '_';
686#ifdef __APPLE__
687 while((i = strchr(result, '/')))
688 *i = '_';
689#endif
690 return result;
691}
692
693/*
694 * Write 'len' bytes from 'buffer' into 'sock'.
695 * returns 0 on success, -1 on failure.
696 */
697static int write_socket(int sock, char *buffer, int len)
698{
699 ssize_t result;
700 int bytes_left = len;
701 while ( bytes_left > 0)
702 {
703 result = write(sock, buffer, bytes_left);
704 if (result > 0)
705 {
706 buffer += result;
707 bytes_left -= result;
708 }
709 else if (result == 0)
710 return -1;
711 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
712 return -1;
713 }
714 return 0;
715}
716
717/*
718 * Read 'len' bytes from 'sock' into 'buffer'.
719 * returns 0 on success, -1 on failure.
720 */
721static int read_socket(int sock, char *buffer, int len)
722{
723 ssize_t result;
724 int bytes_left = len;
725 while ( bytes_left > 0)
726 {
727 result = read(sock, buffer, bytes_left);
728 if (result > 0)
729 {
730 buffer += result;
731 bytes_left -= result;
732 }
733 else if (result == 0)
734 return -1;
735 else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
736 return -1;
737 }
738 return 0;
739}
740
741static int openSocket()
742{
743 kde_socklen_t socklen;
744 int s;
745 struct sockaddr_un server;
746#define MAX_SOCK_FILE 255
747 char sock_file[MAX_SOCK_FILE + 1];
748 const char *home_dir = getenv("HOME");
749 const char *kde_home = getenv("KDEHOME");
750 char *display;
751
752 sock_file[0] = sock_file[MAX_SOCK_FILE] = 0;
753
754 if (!kde_home || !kde_home[0])
755 {
756 kde_home = "~/" KDE_DEFAULT_HOME "/";
757 }
758
759 if (kde_home[0] == '~')
760 {
761 if (!home_dir || !home_dir[0])
762 {
763 fprintf(stderr, "Warning: $HOME not set!\n");
764 return -1;
765 }
766 if (strlen(home_dir) > (MAX_SOCK_FILE-100))
767 {
768 fprintf(stderr, "Warning: Home directory path too long!\n");
769 return -1;
770 }
771 kde_home++;
772 strlcpy(sock_file, home_dir, MAX_SOCK_FILE);
773 }
774 strlcat(sock_file, kde_home, MAX_SOCK_FILE);
775
777 if ( sock_file[strlen(sock_file)-1] == '/')
778 sock_file[strlen(sock_file)-1] = 0;
779
780 strlcat(sock_file, "/socket-", MAX_SOCK_FILE);
781 if (gethostname(sock_file+strlen(sock_file), MAX_SOCK_FILE - strlen(sock_file) - 1) != 0)
782 {
783 perror("Warning: Could not determine hostname: ");
784 return -1;
785 }
786 sock_file[sizeof(sock_file)-1] = '\0';
787
788 /* append $DISPLAY */
789 display = getDisplay();
790 if (display == NULL)
791 {
792 fprintf(stderr, "Error: Could not determine display.\n");
793 return -1;
794 }
795
796 if (strlen(sock_file)+strlen(display)+strlen("/kdeinit4_")+2 > MAX_SOCK_FILE)
797 {
798 fprintf(stderr, "Warning: Socket name will be too long.\n");
799 free(display);
800 return -1;
801 }
802 strcat(sock_file, "/kdeinit4_");
803 strcat(sock_file, display);
804 free(display);
805
806 if (strlen(sock_file) >= sizeof(server.sun_path))
807 {
808 fprintf(stderr, "Warning: Path of socketfile exceeds UNIX_PATH_MAX.\n");
809 return -1;
810 }
811
812 /*
813 * create the socket stream
814 */
815 s = socket(PF_UNIX, SOCK_STREAM, 0);
816 if (s < 0)
817 {
818 perror("Warning: socket() failed: ");
819 return -1;
820 }
821
822 server.sun_family = AF_UNIX;
823 strcpy(server.sun_path, sock_file);
824 // Use stderr, to make the message visible on the Apple OS X Console log.
825 fprintf(stderr, "KCrash: Connect sock_file=%s\n", sock_file);
826 socklen = sizeof(server);
827 if(connect(s, (struct sockaddr *)&server, socklen) == -1)
828 {
829 perror("Warning: connect() failed: ");
830 close(s);
831 return -1;
832 }
833 return s;
834}
835
836#endif // Q_OS_UNIX
KAboutData
KAboutData::internalBugAddress
const char * internalBugAddress() const
KAboutData::internalVersion
const char * internalVersion() const
KAboutData::internalProgramName
const char * internalProgramName() const
KApplication::loadedByKdeinit
static bool loadedByKdeinit
Definition: kapplication.h:404
KCmdLineArgs
KCmdLineArgs::isSet
bool isSet(const QByteArray &option) const
KCmdLineArgs::allArguments
static QStringList allArguments()
KCmdLineArgs::parsedArgs
static KCmdLineArgs * parsedArgs(const QByteArray &id=QByteArray())
KComponentData
KComponentData::isValid
bool isValid() const
KComponentData::aboutData
const KAboutData * aboutData() const
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
QObject
header
const char header[]
mask
#define mask
kaboutdata.h
kapplication.h
kapp
#define kapp
Definition: kapplication.h:56
kcmdlineargs.h
kcomponentdata.h
closeAllFDs
static void closeAllFDs()
Definition: kcrash.cpp:286
s_emergencySaveFunction
static KCrash::HandlerType s_emergencySaveFunction
Definition: kcrash.cpp:80
s_autoRestartArgc
static int s_autoRestartArgc
Definition: kcrash.cpp:85
s_drkonqiPath
static char * s_drkonqiPath
Definition: kcrash.cpp:87
s_autoRestartCommand
static char * s_autoRestartCommand
Definition: kcrash.cpp:83
s_crashHandler
static KCrash::HandlerType s_crashHandler
Definition: kcrash.cpp:81
s_flags
static KCrash::CrashFlags s_flags
Definition: kcrash.cpp:88
s_appName
static char * s_appName
Definition: kcrash.cpp:82
s_launchDrKonqi
static bool s_launchDrKonqi
Definition: kcrash.cpp:89
s_autoRestartCommandLine
static char ** s_autoRestartCommandLine
Definition: kcrash.cpp:86
s_appPath
static char * s_appPath
Definition: kcrash.cpp:84
kcrash.h
perror
QDebug perror(QDebug s, KDebugTag)
kdebug.h
kglobal.h
kstandarddirs.h
KCrash
This namespace contains functions to handle crashes.
Definition: kcrash.cpp:92
KCrash::setCrashHandler
void setCrashHandler(HandlerType handler=defaultCrashHandler)
Install a function to be called when a crash occurs.
Definition: kcrash.cpp:234
KCrash::crashHandler
HandlerType crashHandler()
Returns the installed crash handler.
Definition: kcrash.cpp:280
KCrash::defaultCrashHandler
void defaultCrashHandler(int signal)
The default crash handler.
Definition: kcrash.cpp:296
KCrash::setApplicationPath
void setApplicationPath(const QString &path)
Sets the application path which should be passed to DrKonqi, our nice crash display application.
Definition: kcrash.cpp:161
KCrash::setDrKonqiEnabled
void setDrKonqiEnabled(bool enabled)
Enables or disables launching DrKonqi from the crash handler.
Definition: kcrash.cpp:204
KCrash::setEmergencySaveFunction
void setEmergencySaveFunction(HandlerType saveFunction=0)
Installs a function which should try to save the application's data.
Definition: kcrash.cpp:101
KCrash::HandlerType
void(* HandlerType)(int)
Typedef for a pointer to a crash handler function.
Definition: kcrash.h:63
KCrash::setFlags
void setFlags(CrashFlags flags)
Set options to determine how the default crash handler should behave.
KCrash::setApplicationName
void setApplicationName(const QString &name)
Sets the application name which should be passed to DrKonqi, our nice crash display application.
Definition: kcrash.cpp:187
KCrash::emergencySaveFunction
HandlerType emergencySaveFunction()
Returns the currently set emergency save function.
Definition: kcrash.cpp:115
KCrash::startProcess
void startProcess(int argc, const char *argv[], bool waitAndExit)
Definition: kcrash.cpp:461
KCrash::isDrKonqiEnabled
bool isDrKonqiEnabled()
Returns true if DrKonqi is set to be launched from the crash handler or false otherwise.
Definition: kcrash.cpp:228
KCrash::AutoRestart
@ AutoRestart
autorestart this application. Only sensible for KUniqueApplications.
Definition: kcrash.h:111
KCrash::SaferDialog
@ SaferDialog
start DrKonqi without arbitrary disk access
Definition: kcrash.h:109
KCrash::KeepFDs
@ KeepFDs
don't close all file descriptors immediately
Definition: kcrash.h:108
KCrash::win32UnhandledExceptionFilter
LONG WINAPI win32UnhandledExceptionFilter(_EXCEPTION_POINTERS *exceptionInfo)
Definition: kcrash.cpp:488
KGlobal::mainComponent
const KComponentData & mainComponent()
KStandardAction::close
KAction * close(const QObject *recvr, const char *slot, QObject *parent)
Close the current document.
Definition: kstandardaction.cpp:269
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal