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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • 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 
80 static KCrash::HandlerType s_emergencySaveFunction = 0;
81 static KCrash::HandlerType s_crashHandler = 0;
82 static char *s_appName = 0;
83 static char *s_autoRestartCommand = 0;
84 static char *s_appPath = 0;
85 static int s_autoRestartArgc = 0;
86 static char **s_autoRestartCommandLine = 0;
87 static char *s_drkonqiPath = 0;
88 static KCrash::CrashFlags s_flags = 0;
89 static bool s_launchDrKonqi = false;
90 
91 namespace 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 
100 void
101 KCrash::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 
114 KCrash::HandlerType
115 KCrash::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.
126 class KCrashDelaySetHandler : public QObject
127 {
128 public:
129  KCrashDelaySetHandler() {
130  startTimer(10000); // 10 s
131  }
132 protected:
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 
143 void
144 KCrash::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.
160 void
161 KCrash::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 
186 void
187 KCrash::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 
204 void KCrash::setDrKonqiEnabled(bool enabled)
205 {
206  s_launchDrKonqi = enabled;
207  if (s_launchDrKonqi && !s_drkonqiPath) {
208  s_drkonqiPath = qstrdup(QFile::encodeName(KStandardDirs::findExe("drkonqi")).constData());
209  if (!s_drkonqiPath) {
210  kError() << "Could not find drkonqi";
211  s_launchDrKonqi = false;
212  }
213  }
214 
215  //we need at least the default crash handler to launch drkonqi
216  if (s_launchDrKonqi && !s_crashHandler) {
217  setCrashHandler(defaultCrashHandler);
218  }
219 }
220 
221 bool KCrash::isDrKonqiEnabled()
222 {
223  return s_launchDrKonqi;
224 }
225 
226 void
227 KCrash::setCrashHandler (HandlerType handler)
228 {
229 #if defined(Q_OS_WIN)
230  static LPTOP_LEVEL_EXCEPTION_FILTER s_previousExceptionFilter = NULL;
231 
232  if (handler && !s_previousExceptionFilter) {
233  s_previousExceptionFilter = SetUnhandledExceptionFilter(KCrash::win32UnhandledExceptionFilter);
234  } else if (!handler && s_previousExceptionFilter) {
235  SetUnhandledExceptionFilter(s_previousExceptionFilter);
236  s_previousExceptionFilter = NULL;
237  }
238 #else
239  if (!handler)
240  handler = SIG_DFL;
241 
242  sigset_t mask;
243  sigemptyset(&mask);
244 
245 #ifdef SIGSEGV
246  signal (SIGSEGV, handler);
247  sigaddset(&mask, SIGSEGV);
248 #endif
249 #ifdef SIGBUS
250  signal (SIGBUS, handler);
251  sigaddset(&mask, SIGBUS);
252 #endif
253 #ifdef SIGFPE
254  signal (SIGFPE, handler);
255  sigaddset(&mask, SIGFPE);
256 #endif
257 #ifdef SIGILL
258  signal (SIGILL, handler);
259  sigaddset(&mask, SIGILL);
260 #endif
261 #ifdef SIGABRT
262  signal (SIGABRT, handler);
263  sigaddset(&mask, SIGABRT);
264 #endif
265 
266  sigprocmask(SIG_UNBLOCK, &mask, 0);
267 #endif
268 
269  s_crashHandler = handler;
270 }
271 
272 KCrash::HandlerType
273 KCrash::crashHandler()
274 {
275  return s_crashHandler;
276 }
277 
278 static void
279 closeAllFDs()
280 {
281  // Close all remaining file descriptors except for stdin/stdout/stderr
282  struct rlimit rlp;
283  getrlimit(RLIMIT_NOFILE, &rlp);
284  for (int i = 3; i < (int)rlp.rlim_cur; i++)
285  close(i);
286 }
287 
288 void
289 KCrash::defaultCrashHandler (int sig)
290 {
291  // WABA: Do NOT use kDebug() in this function because it is much too risky!
292  // Handle possible recursions
293  static int crashRecursionCounter = 0;
294  crashRecursionCounter++; // Nothing before this, please !
295 
296 #if !defined(Q_OS_WIN)
297  signal(SIGALRM, SIG_DFL);
298  alarm(3); // Kill me... (in case we deadlock in malloc)
299 #endif
300 
301 #ifdef Q_OS_SOLARIS
302  (void) printstack(2 /* stderr, assuming it's still open. */);
303 #endif
304 
305  if (crashRecursionCounter < 2) {
306  if (s_emergencySaveFunction) {
307  s_emergencySaveFunction (sig);
308  }
309  if ((s_flags & AutoRestart) && s_autoRestartCommand) {
310  sleep(1);
311  startProcess(s_autoRestartArgc, const_cast<const char**>(s_autoRestartCommandLine), false);
312  }
313  crashRecursionCounter++;
314  }
315 
316  // On Apple OS X, closing all FDs now will cause a second (SIGILL) crash,
317  // ending with "Unable to start Dr. Konqi". This is because the libdispatch
318  // library, which can manage multi-threading, has some FDs of its own.
319  //
320  // Note: KCrash closes FDs unconditionally later on if it forks to Dr Konqi
321  // and this program's FDs do not matter if kdeinit starts Dr Konqi.
322 #if !defined(Q_OS_WIN) and !defined(Q_OS_MAC)
323  if (!(s_flags & KeepFDs))
324  closeAllFDs();
325 # if defined(Q_WS_X11)
326  else if (QX11Info::display())
327  close(ConnectionNumber(QX11Info::display()));
328 # endif
329 #endif
330 
331  if (crashRecursionCounter < 3)
332  {
333 #ifndef NDEBUG
334  fprintf(stderr, "KCrash: crashing... crashRecursionCounter = %d\n",
335  crashRecursionCounter);
336  fprintf(stderr, "KCrash: Application Name = %s path = %s pid = %lld\n",
337  s_appName ? s_appName : "<unknown>" ,
338  s_appPath ? s_appPath : "<unknown>", QCoreApplication::applicationPid());
339  fprintf(stderr, "KCrash: Arguments: ");
340  for (int i = 0; s_autoRestartCommandLine[i]; ++i) {
341  fprintf(stderr, "%s ", s_autoRestartCommandLine[i]);
342  }
343  fprintf(stderr, "\n");
344 #else
345  fprintf(stderr, "KCrash: Application '%s' crashing...\n",
346  s_appName ? s_appName : "<unknown>");
347 #endif
348 
349  if (!s_launchDrKonqi) {
350  setCrashHandler(0);
351 #if !defined(Q_OS_WIN)
352  raise(sig); // dump core, or whatever is the default action for this signal.
353 #endif
354  return;
355  }
356 
357  const char * argv[27]; // don't forget to update this
358  int i = 0;
359 
360  // argument 0 has to be drkonqi
361  argv[i++] = s_drkonqiPath;
362 
363 #if defined Q_WS_X11
364  // start up on the correct display
365  argv[i++] = "-display";
366  if ( QX11Info::display() )
367  argv[i++] = XDisplayString(QX11Info::display());
368  else
369  argv[i++] = getenv("DISPLAY");
370 #elif defined(Q_WS_QWS)
371  // start up on the correct display
372  argv[i++] = "-display";
373  argv[i++] = getenv("QWS_DISPLAY");
374 #endif
375 
376  argv[i++] = "--appname";
377  argv[i++] = s_appName ? s_appName : "<unknown>";
378 
379  if (KApplication::loadedByKdeinit)
380  argv[i++] = "--kdeinit";
381 
382  // only add apppath if it's not NULL
383  if (s_appPath && *s_appPath) {
384  argv[i++] = "--apppath";
385  argv[i++] = s_appPath;
386  }
387 
388  // signal number -- will never be NULL
389  char sigtxt[ 10 ];
390  sprintf( sigtxt, "%d", sig );
391  argv[i++] = "--signal";
392  argv[i++] = sigtxt;
393 
394  char pidtxt[ 20 ];
395  sprintf( pidtxt, "%lld", QCoreApplication::applicationPid());
396  argv[i++] = "--pid";
397  argv[i++] = pidtxt;
398 
399  const KComponentData componentData = KGlobal::mainComponent();
400  const KAboutData *about = componentData.isValid() ? componentData.aboutData() : 0;
401  if (about) {
402  if (about->internalVersion()) {
403  argv[i++] = "--appversion";
404  argv[i++] = about->internalVersion();
405  }
406 
407  if (about->internalProgramName()) {
408  argv[i++] = "--programname";
409  argv[i++] = about->internalProgramName();
410  }
411 
412  if (about->internalBugAddress()) {
413  argv[i++] = "--bugaddress";
414  argv[i++] = about->internalBugAddress();
415  }
416  }
417 
418  char sidtxt[256];
419  if ( kapp && !kapp->startupId().isNull()) {
420  argv[i++] = "--startupid";
421  strlcpy(sidtxt, kapp->startupId().constData(), sizeof(sidtxt));
422  argv[i++] = sidtxt;
423  }
424 
425  if ( s_flags & SaferDialog )
426  argv[i++] = "--safer";
427 
428  if ((s_flags & AutoRestart) && s_autoRestartCommand)
429  argv[i++] = "--restarted"; //tell drkonqi if the app has been restarted
430 
431 #if defined(Q_OS_WIN)
432  char threadId[8] = { 0 };
433  sprintf( threadId, "%d", GetCurrentThreadId() );
434  argv[i++] = "--thread";
435  argv[i++] = threadId;
436 #endif
437 
438  // NULL terminated list
439  argv[i] = NULL;
440 
441  startProcess(i, argv, true);
442  }
443 
444  if (crashRecursionCounter < 4)
445  {
446  fprintf(stderr, "Unable to start Dr. Konqi\n");
447  }
448 
449  _exit(255);
450 }
451 
452 #if defined(Q_OS_WIN)
453 
454 void KCrash::startProcess(int argc, const char *argv[], bool waitAndExit)
455 {
456  QString cmdLine;
457  for(int i=0; i<argc; ++i) {
458  cmdLine.append('\"');
459  cmdLine.append(QFile::decodeName(argv[i]));
460  cmdLine.append("\" ");
461  }
462 
463  PROCESS_INFORMATION procInfo;
464  STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
465  (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
466  (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
467  0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
468 
469  bool success = CreateProcess(0, (wchar_t*) cmdLine.utf16(), NULL, NULL,
470  false, CREATE_UNICODE_ENVIRONMENT, NULL, NULL,
471  &startupInfo, &procInfo);
472 
473  if (success && waitAndExit) {
474  // wait for child to exit
475  WaitForSingleObject(procInfo.hProcess, INFINITE);
476  _exit(253);
477  }
478 }
479 
480 //glue function for calling the unix signal handler from the windows unhandled exception filter
481 LONG WINAPI KCrash::win32UnhandledExceptionFilter(_EXCEPTION_POINTERS *exceptionInfo)
482 {
483  // kdbgwin needs the context inside exceptionInfo because if getting the context after the
484  // exception happened, it will walk down the stack and will stop at KiUserEventDispatch in
485  // ntdll.dll, which is supposed to dispatch the exception from kernel mode back to user mode
486  // so... let's create some shared memory
487  HANDLE hMapFile = NULL;
488  hMapFile = CreateFileMapping(
489  INVALID_HANDLE_VALUE,
490  NULL,
491  PAGE_READWRITE,
492  0,
493  sizeof(CONTEXT),
494  TEXT("Local\\KCrashShared"));
495 
496  LPCTSTR pBuf = NULL;
497  pBuf = (LPCTSTR) MapViewOfFile(
498  hMapFile,
499  FILE_MAP_ALL_ACCESS,
500  0,
501  0,
502  sizeof(CONTEXT));
503  CopyMemory((PVOID) pBuf, exceptionInfo->ContextRecord, sizeof(CONTEXT));
504 
505  if (s_crashHandler) {
506  s_crashHandler(exceptionInfo->ExceptionRecord->ExceptionCode);
507  }
508 
509  CloseHandle(hMapFile);
510  return EXCEPTION_EXECUTE_HANDLER; //allow windows to do the default action (terminate)
511 }
512 #else
513 
514 static bool startProcessInternal(int argc, const char *argv[], bool waitAndExit, bool directly);
515 static pid_t startFromKdeinit(int argc, const char *argv[]);
516 static pid_t startDirectly(const char *argv[]);
517 static int write_socket(int sock, char *buffer, int len);
518 static int read_socket(int sock, char *buffer, int len);
519 static int openSocket();
520 
521 void KCrash::startProcess(int argc, const char *argv[], bool waitAndExit)
522 {
523  bool startDirectly = true;
524 
525  // First try to start the app via kdeinit, if the AlwaysDirectly flag hasn't been specified.
526  // This is done because it is dangerous to use fork() in the crash handler
527  // (there can be functions registered to be performed before fork(), for example handling
528  // of malloc locking, which doesn't work when malloc crashes because of heap corruption).
529 #ifndef Q_OS_MAC
530  // Fails on Apple OSX+KDE4, because kdeinit4 is using the wrong socket name.
531  if (!(s_flags & AlwaysDirectly)) {
532  startDirectly = !startProcessInternal(argc, argv, waitAndExit, false);
533  }
534 #endif
535 
536  // If we can't reach kdeinit, we can still at least try to fork()
537  if (startDirectly) {
538  startProcessInternal(argc, argv, waitAndExit, true);
539  }
540 }
541 
542 static bool startProcessInternal(int argc, const char *argv[], bool waitAndExit, bool directly)
543 {
544  fprintf(stderr, "KCrash: Attempting to start %s %s\n", argv[0], directly ? "directly" : "from kdeinit");
545 
546  pid_t pid = directly ? startDirectly(argv) : startFromKdeinit(argc, argv);
547 
548  if (pid > 0 && waitAndExit) {
549  // Seems we made it....
550  alarm(0); //stop the pending alarm that was set at the top of the defaultCrashHandler
551 
552  // Wait forever until the started process exits. This code path is executed
553  // when launching drkonqi. Note that drkonqi will stop this process in the meantime.
554  if (directly) {
555  //if the process was started directly, use waitpid(), as it's a child...
556  while(waitpid(-1, NULL, 0) != pid) {}
557  } else {
558 #ifdef Q_OS_LINUX
559  // Declare the process that will be debugging the crashed KDE app (#245529)
560 #ifndef PR_SET_PTRACER
561 # define PR_SET_PTRACER 0x59616d61
562 #endif
563  prctl(PR_SET_PTRACER, pid, 0, 0, 0);
564 #endif
565  //...else poll its status using kill()
566  while(kill(pid, 0) >= 0) {
567  sleep(1);
568  }
569  }
570  _exit(253);
571  }
572 
573  return (pid > 0); //return true on success
574 }
575 
576 static pid_t startFromKdeinit(int argc, const char *argv[])
577 {
578  int socket = openSocket();
579  if( socket < -1 )
580  return 0;
581  klauncher_header header;
582  header.cmd = LAUNCHER_EXEC_NEW;
583  const int BUFSIZE = 8192; // make sure this is big enough
584  char buffer[ BUFSIZE + 10 ];
585  int pos = 0;
586  long argcl = argc;
587  memcpy( buffer + pos, &argcl, sizeof( argcl ));
588  pos += sizeof( argcl );
589  for( int i = 0;
590  i < argc;
591  ++i )
592  {
593  int len = strlen( argv[ i ] ) + 1; // include terminating \0
594  if( pos + len >= BUFSIZE )
595  {
596  fprintf( stderr, "BUFSIZE in KCrash not big enough!\n" );
597  return 0;
598  }
599  memcpy( buffer + pos, argv[ i ], len );
600  pos += len;
601  }
602  long env = 0;
603  memcpy( buffer + pos, &env, sizeof( env ));
604  pos += sizeof( env );
605  long avoid_loops = 0;
606  memcpy( buffer + pos, &avoid_loops, sizeof( avoid_loops ));
607  pos += sizeof( avoid_loops );
608  header.arg_length = pos;
609  write_socket(socket, (char *) &header, sizeof(header));
610  write_socket(socket, buffer, pos);
611  if( read_socket( socket, (char *) &header, sizeof(header)) < 0
612  || header.cmd != LAUNCHER_OK )
613  {
614  return 0;
615  }
616  long pid;
617  read_socket(socket, (char *) &pid, sizeof(pid));
618  return static_cast<pid_t>(pid);
619 }
620 
621 static pid_t startDirectly(const char *argv[])
622 {
623  pid_t pid = fork();
624  switch (pid)
625  {
626  case -1:
627  fprintf( stderr, "KCrash failed to fork(), errno = %d\n", errno );
628  return 0;
629  case 0:
630  if (setgid(getgid()) < 0 || setuid(getuid()) < 0)
631  _exit(253); // This cannot happen. Theoretically.
632  closeAllFDs(); // We are in the child now. Close FDs unconditionally.
633  execvp(argv[0], const_cast< char** >(argv));
634  fprintf( stderr, "KCrash failed to exec(), errno = %d\n", errno );
635  _exit(253);
636  default:
637  return pid;
638  }
639 }
640 
641 // From now on this code is copy&pasted from kinit/wrapper.c :
642 
643 static char *getDisplay()
644 {
645  const char *display;
646  char *result;
647  char *screen;
648  char *colon;
649  char *i;
650 /*
651  don't test for a value from qglobal.h but instead distinguish
652  Qt/X11 from Qt/Embedded by the fact that Qt/E apps have -DQWS
653  on the commandline (which in qglobal.h however triggers Q_WS_QWS,
654  but we don't want to include that here) (Simon)
655 #ifdef Q_WS_X11
656  */
657 #ifdef NO_DISPLAY
658  display = "NODISPLAY";
659 #elif !defined(QWS)
660  display = getenv("DISPLAY");
661 #else
662  display = getenv("QWS_DISPLAY");
663 #endif
664  if (!display || !*display)
665  {
666  display = ":0";
667  }
668  result = (char*)malloc(strlen(display)+1);
669  if (result == NULL)
670  return NULL;
671 
672  strcpy(result, display);
673  screen = strrchr(result, '.');
674  colon = strrchr(result, ':');
675  if (screen && (screen > colon))
676  *screen = '\0';
677  while((i = strchr(result, ':')))
678  *i = '_';
679 #ifdef __APPLE__
680  while((i = strchr(result, '/')))
681  *i = '_';
682 #endif
683  return result;
684 }
685 
686 /*
687  * Write 'len' bytes from 'buffer' into 'sock'.
688  * returns 0 on success, -1 on failure.
689  */
690 static int write_socket(int sock, char *buffer, int len)
691 {
692  ssize_t result;
693  int bytes_left = len;
694  while ( bytes_left > 0)
695  {
696  result = write(sock, buffer, bytes_left);
697  if (result > 0)
698  {
699  buffer += result;
700  bytes_left -= result;
701  }
702  else if (result == 0)
703  return -1;
704  else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
705  return -1;
706  }
707  return 0;
708 }
709 
710 /*
711  * Read 'len' bytes from 'sock' into 'buffer'.
712  * returns 0 on success, -1 on failure.
713  */
714 static int read_socket(int sock, char *buffer, int len)
715 {
716  ssize_t result;
717  int bytes_left = len;
718  while ( bytes_left > 0)
719  {
720  result = read(sock, buffer, bytes_left);
721  if (result > 0)
722  {
723  buffer += result;
724  bytes_left -= result;
725  }
726  else if (result == 0)
727  return -1;
728  else if ((result == -1) && (errno != EINTR) && (errno != EAGAIN))
729  return -1;
730  }
731  return 0;
732 }
733 
734 static int openSocket()
735 {
736  kde_socklen_t socklen;
737  int s;
738  struct sockaddr_un server;
739 #define MAX_SOCK_FILE 255
740  char sock_file[MAX_SOCK_FILE + 1];
741  const char *home_dir = getenv("HOME");
742  const char *kde_home = getenv("KDEHOME");
743  char *display;
744 
745  sock_file[0] = sock_file[MAX_SOCK_FILE] = 0;
746 
747  if (!kde_home || !kde_home[0])
748  {
749  kde_home = "~/" KDE_DEFAULT_HOME "/";
750  }
751 
752  if (kde_home[0] == '~')
753  {
754  if (!home_dir || !home_dir[0])
755  {
756  fprintf(stderr, "Warning: $HOME not set!\n");
757  return -1;
758  }
759  if (strlen(home_dir) > (MAX_SOCK_FILE-100))
760  {
761  fprintf(stderr, "Warning: Home directory path too long!\n");
762  return -1;
763  }
764  kde_home++;
765  strlcpy(sock_file, home_dir, MAX_SOCK_FILE);
766  }
767  strlcat(sock_file, kde_home, MAX_SOCK_FILE);
768 
770  if ( sock_file[strlen(sock_file)-1] == '/')
771  sock_file[strlen(sock_file)-1] = 0;
772 
773  strlcat(sock_file, "/socket-", MAX_SOCK_FILE);
774  if (gethostname(sock_file+strlen(sock_file), MAX_SOCK_FILE - strlen(sock_file) - 1) != 0)
775  {
776  perror("Warning: Could not determine hostname: ");
777  return -1;
778  }
779  sock_file[sizeof(sock_file)-1] = '\0';
780 
781  /* append $DISPLAY */
782  display = getDisplay();
783  if (display == NULL)
784  {
785  fprintf(stderr, "Error: Could not determine display.\n");
786  return -1;
787  }
788 
789  if (strlen(sock_file)+strlen(display)+strlen("/kdeinit4_")+2 > MAX_SOCK_FILE)
790  {
791  fprintf(stderr, "Warning: Socket name will be too long.\n");
792  free(display);
793  return -1;
794  }
795  strcat(sock_file, "/kdeinit4_");
796  strcat(sock_file, display);
797  free(display);
798 
799  if (strlen(sock_file) >= sizeof(server.sun_path))
800  {
801  fprintf(stderr, "Warning: Path of socketfile exceeds UNIX_PATH_MAX.\n");
802  return -1;
803  }
804 
805  /*
806  * create the socket stream
807  */
808  s = socket(PF_UNIX, SOCK_STREAM, 0);
809  if (s < 0)
810  {
811  perror("Warning: socket() failed: ");
812  return -1;
813  }
814 
815  server.sun_family = AF_UNIX;
816  strcpy(server.sun_path, sock_file);
817  // Use stderr, to make the message visible on the Apple OS X Console log.
818  fprintf(stderr, "KCrash: Connect sock_file=%s\n", sock_file);
819  socklen = sizeof(server);
820  if(connect(s, (struct sockaddr *)&server, socklen) == -1)
821  {
822  perror("Warning: connect() failed: ");
823  close(s);
824  return -1;
825  }
826  return s;
827 }
828 
829 #endif // Q_OS_UNIX
closeAllFDs
static void closeAllFDs()
Definition: kcrash.cpp:279
s_appName
static char * s_appName
Definition: kcrash.cpp:82
kapp
#define kapp
Definition: kapplication.h:56
KAboutData::internalVersion
const char * internalVersion() const
KCmdLineArgs::allArguments
static QStringList allArguments()
QString::append
QString & append(QChar ch)
header
const char header[]
perror
QDebug perror(QDebug s, KDebugTag)
KCrash::HandlerType
void(* HandlerType)(int)
Typedef for a pointer to a crash handler function.
Definition: kcrash.h:63
kdebug.h
kapplication.h
QByteArray
mask
#define mask
KCmdLineArgs::parsedArgs
static KCmdLineArgs * parsedArgs(const QByteArray &id=QByteArray())
QX11Info::display
Display * display()
QList::at
const T & at(int i) const
KCmdLineArgs
KCrash::startProcess
void startProcess(int argc, const char *argv[], bool waitAndExit)
Definition: kcrash.cpp:454
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
KAboutData::internalBugAddress
const char * internalBugAddress() const
KStandardAction::name
const char * name(StandardAction id)
This will return the internal name of a given standard action.
Definition: kstandardaction.cpp:223
KCrash::defaultCrashHandler
void defaultCrashHandler(int signal)
The default crash handler.
Definition: kcrash.cpp:289
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
kError
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KComponentData::aboutData
const KAboutData * aboutData() const
s_autoRestartCommandLine
static char ** s_autoRestartCommandLine
Definition: kcrash.cpp:86
QObject::timerEvent
virtual void timerEvent(QTimerEvent *event)
s_drkonqiPath
static char * s_drkonqiPath
Definition: kcrash.cpp:87
KCmdLineArgs::isSet
bool isSet(const QByteArray &option) const
QTimerEvent
kglobal.h
QList::count
int count(const T &value) const
s_autoRestartArgc
static int s_autoRestartArgc
Definition: kcrash.cpp:85
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
QObject
s_crashHandler
static KCrash::HandlerType s_crashHandler
Definition: kcrash.cpp:81
KCrash::setEmergencySaveFunction
void setEmergencySaveFunction(HandlerType saveFunction=0)
Installs a function which should try to save the application's data.
Definition: kcrash.cpp:101
kcmdlineargs.h
QFileInfo::absoluteFilePath
QString absoluteFilePath() const
QByteArray::constData
const char * constData() const
KCrash::KeepFDs
don't close all file descriptors immediately
Definition: kcrash.h:108
KAboutData
KCrash::isDrKonqiEnabled
bool isDrKonqiEnabled()
Returns true if DrKonqi is set to be launched from the crash handler or false otherwise.
Definition: kcrash.cpp:221
QCoreApplication::applicationPid
qint64 applicationPid()
QObject::deleteLater
void deleteLater()
kcrash.h
QString
KCrash::emergencySaveFunction
HandlerType emergencySaveFunction()
Returns the currently set emergency save function.
Definition: kcrash.cpp:115
s_emergencySaveFunction
static KCrash::HandlerType s_emergencySaveFunction
Definition: kcrash.cpp:80
QStringList
s_appPath
static char * s_appPath
Definition: kcrash.cpp:84
QFileInfo
KCrash::AutoRestart
autorestart this application. Only sensible for KUniqueApplications.
Definition: kcrash.h:111
QDir
QObject::startTimer
int startTimer(int interval)
s_launchDrKonqi
static bool s_launchDrKonqi
Definition: kcrash.cpp:89
QString::utf16
const ushort * utf16() const
KCrash::AlwaysDirectly
never try to to start DrKonqi via kdeinit. Use fork() and exec() instead.
Definition: kcrash.h:110
KCrash::SaferDialog
start DrKonqi without arbitrary disk access
Definition: kcrash.h:109
QList::insert
void insert(int i, const T &value)
kstandarddirs.h
s_autoRestartCommand
static char * s_autoRestartCommand
Definition: kcrash.cpp:83
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
KComponentData::isValid
bool isValid() const
KGlobal::mainComponent
const KComponentData & mainComponent()
KCrash::crashHandler
HandlerType crashHandler()
Returns the installed crash handler.
Definition: kcrash.cpp:273
QTimerEvent::timerId
int timerId() const
KCrash::setDrKonqiEnabled
void setDrKonqiEnabled(bool enabled)
Enables or disables launching DrKonqi from the crash handler.
Definition: kcrash.cpp:204
KAboutData::internalProgramName
const char * internalProgramName() const
KCrash::setFlags
void setFlags(CrashFlags flags)
Set options to determine how the default crash handler should behave.
kaboutdata.h
s_flags
static KCrash::CrashFlags s_flags
Definition: kcrash.cpp:88
KApplication::loadedByKdeinit
static bool loadedByKdeinit
Definition: kapplication.h:404
kcomponentdata.h
QObject::killTimer
void killTimer(int id)
KComponentData
KStandardAction::close
KAction * close(const QObject *recvr, const char *slot, QObject *parent)
Close the current document.
Definition: kstandardaction.cpp:269
QFile::encodeName
QByteArray encodeName(const QString &fileName)
QFile::decodeName
QString decodeName(const QByteArray &localFileName)
KCrash::setCrashHandler
void setCrashHandler(HandlerType handler=defaultCrashHandler)
Install a function to be called when a crash occurs.
Definition: kcrash.cpp:227
KCrash::win32UnhandledExceptionFilter
LONG WINAPI win32UnhandledExceptionFilter(_EXCEPTION_POINTERS *exceptionInfo)
Definition: kcrash.cpp:481
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:23:59 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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