LCOV - code coverage report
Current view: top level - toolkit/xre - nsX11ErrorHandler.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 54 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsX11ErrorHandler.h"
       7             : 
       8             : #include "prenv.h"
       9             : #include "nsXULAppAPI.h"
      10             : #include "nsExceptionHandler.h"
      11             : #include "nsDebug.h"
      12             : 
      13             : #include "mozilla/X11Util.h"
      14             : #include <X11/Xlib.h>
      15             : 
      16             : #define BUFSIZE 2048 // What Xlib uses with XGetErrorDatabaseText
      17             : 
      18             : extern "C" {
      19             : int
      20           0 : X11Error(Display *display, XErrorEvent *event) {
      21             :   // Get an indication of how long ago the request that caused the error was
      22             :   // made.
      23           0 :   unsigned long age = NextRequest(display) - event->serial;
      24             : 
      25             :   // Get a string to represent the request that caused the error.
      26           0 :   nsAutoCString message;
      27           0 :   if (event->request_code < 128) {
      28             :     // Core protocol request
      29           0 :     message.AppendInt(event->request_code);
      30             :   } else {
      31             :     // Extension request
      32             : 
      33             :     // man XSetErrorHandler says "the error handler should not call any
      34             :     // functions (directly or indirectly) on the display that will generate
      35             :     // protocol requests or that will look for input events" so we use another
      36             :     // temporary Display to request extension information.  This assumes on
      37             :     // the DISPLAY environment variable has been set and matches what was used
      38             :     // to open |display|.
      39           0 :     Display *tmpDisplay = XOpenDisplay(nullptr);
      40           0 :     if (tmpDisplay) {
      41             :       int nExts;
      42           0 :       char** extNames = XListExtensions(tmpDisplay, &nExts);
      43             :       int first_error;
      44           0 :       if (extNames) {
      45           0 :         for (int i = 0; i < nExts; ++i) {
      46             :           int major_opcode, first_event;
      47           0 :           if (XQueryExtension(tmpDisplay, extNames[i],
      48             :                               &major_opcode, &first_event, &first_error)
      49           0 :               && major_opcode == event->request_code) {
      50           0 :             message.Append(extNames[i]);
      51           0 :             message.Append('.');
      52           0 :             message.AppendInt(event->minor_code);
      53           0 :             break;
      54             :           }
      55             :         }
      56             : 
      57           0 :         XFreeExtensionList(extNames);
      58             :       }
      59           0 :       XCloseDisplay(tmpDisplay);
      60             : 
      61             : #if (MOZ_WIDGET_GTK == 2)
      62             :       // GDK2 calls XCloseDevice the devices that it opened on startup, but
      63             :       // the XI protocol no longer ensures that the devices will still exist.
      64             :       // If they have been removed, then a BadDevice error results.  Ignore
      65             :       // this error.
      66             :       if (message.EqualsLiteral("XInputExtension.4") &&
      67             :           event->error_code == first_error + 0) {
      68             :         return 0;
      69             :       }
      70             : #endif
      71             :     }
      72             :   }
      73             : 
      74             :   char buffer[BUFSIZE];
      75           0 :   if (message.IsEmpty()) {
      76           0 :     buffer[0] = '\0';
      77             :   } else {
      78           0 :     XGetErrorDatabaseText(display, "XRequest", message.get(), "",
      79           0 :                           buffer, sizeof(buffer));
      80             :   }
      81             : 
      82           0 :   nsAutoCString notes;
      83           0 :   if (buffer[0]) {
      84           0 :     notes.Append(buffer);
      85             :   } else {
      86           0 :     notes.AppendLiteral("Request ");
      87           0 :     notes.AppendInt(event->request_code);
      88           0 :     notes.Append('.');
      89           0 :     notes.AppendInt(event->minor_code);
      90             :   }
      91             : 
      92           0 :   notes.AppendLiteral(": ");
      93             : 
      94             :   // Get a string to describe the error.
      95           0 :   XGetErrorText(display, event->error_code, buffer, sizeof(buffer));
      96           0 :   notes.Append(buffer);
      97             : 
      98             :   // For requests where Xlib gets the reply synchronously, |age| will be 1
      99             :   // and the stack will include the function making the request.  For
     100             :   // asynchronous requests, the current stack will often be unrelated to the
     101             :   // point of making the request, even if |age| is 1, but sometimes this may
     102             :   // help us count back to the point of the request.  With XSynchronize on,
     103             :   // the stack will include the function making the request, even though
     104             :   // |age| will be 2 for asynchronous requests because XSynchronize is
     105             :   // implemented by an empty request from an XSync, which has not yet been
     106             :   // processed.
     107           0 :   if (age > 1) {
     108             :     // XSynchronize returns the previous "after function".  If a second
     109             :     // XSynchronize call returns the same function after an enable call then
     110             :     // synchronization must have already been enabled.
     111           0 :     if (XSynchronize(display, True) == XSynchronize(display, False)) {
     112           0 :       notes.AppendLiteral("; sync");
     113             :     } else {
     114           0 :       notes.AppendLiteral("; ");
     115           0 :       notes.AppendInt(uint32_t(age));
     116           0 :       notes.AppendLiteral(" requests ago");
     117             :     }
     118             :   }
     119             : 
     120             : #ifdef MOZ_CRASHREPORTER
     121           0 :   switch (XRE_GetProcessType()) {
     122             :   case GeckoProcessType_Default:
     123             :   case GeckoProcessType_Plugin:
     124             :   case GeckoProcessType_Content:
     125           0 :     CrashReporter::AppendAppNotesToCrashReport(notes);
     126           0 :     break;
     127             :   default:
     128             :     ; // crash report notes not supported.
     129             :   }
     130             : #endif
     131             : 
     132             : #ifdef DEBUG
     133             :   // The resource id is unlikely to be useful in a crash report without
     134             :   // context of other ids, but add it to the debug console output.
     135           0 :   notes.AppendLiteral("; id=0x");
     136           0 :   notes.AppendInt(uint32_t(event->resourceid), 16);
     137             : #ifdef MOZ_X11
     138             :   // Actually, for requests where Xlib gets the reply synchronously,
     139             :   // MOZ_X_SYNC=1 will not be necessary, but we don't have a table to tell us
     140             :   // which requests get a synchronous reply.
     141           0 :   if (!PR_GetEnv("MOZ_X_SYNC")) {
     142           0 :     notes.AppendLiteral("\nRe-running with MOZ_X_SYNC=1 in the environment may give a more helpful backtrace.");
     143             :   }
     144             : #endif
     145             : #endif
     146             : 
     147           0 :   NS_RUNTIMEABORT(notes.get());
     148           0 :   return 0; // not reached
     149             : }
     150             : }
     151             : 
     152             : void
     153           0 : InstallX11ErrorHandler()
     154             : {
     155           0 :   XSetErrorHandler(X11Error);
     156             : 
     157           0 :   Display *display = mozilla::DefaultXDisplay();
     158           0 :   NS_ASSERTION(display, "No X display");
     159           0 :   if (PR_GetEnv("MOZ_X_SYNC")) {
     160           0 :     XSynchronize(display, True);
     161             :   }
     162           0 : }

Generated by: LCOV version 1.13