/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * This function should be used by all modules and fvwm when a X error * occurs and the module exits. */ #include "config.h" #include #include #include #include "FRenderInit.h" #include "XError.h" #undef XSetErrorHandler #define USE_GET_ERROR_TEXT 1 #ifndef USE_GET_ERROR_TEXT static char *error_name(unsigned char code); #endif static char *request_name(unsigned char code); static char unknown[32]; void do_coredump(void) { fprintf(stderr, " Leaving a core dump now\n"); { char *nullp; nullp = NULL; *nullp = 99; } /* exit if this fails */ exit(99); } #define USE_GET_ERROR_TEXT 1 void PrintXErrorAndCoredump(Display *dpy, XErrorEvent *error, char *MyName) { char msg[256]; Bool suc = False; msg[255] = 0; #ifdef USE_GET_ERROR_TEXT /* can't call this from within an error handler! */ /* DV (21-Nov-2000): Well, actually we *can* call it in an error * handler since it does not trigger a protocol request. */ if (error->error_code >= FirstExtensionError) { suc = FRenderGetErrorText(error->error_code, msg); } if (!suc) XGetErrorText(dpy, error->error_code, msg, sizeof(msg)); fprintf(stderr,"%s: Cause of next X Error.\n", MyName); fprintf(stderr, " Error: %d (%s)\n", error->error_code, msg); #else fprintf(stderr,"%s: Cause of next X Error.\n", MyName); if (error->error_code >= FirstExtensionError) { suc = FRenderGetErrorText(error->error_code, msg); } if (suc) fprintf(stderr, " Error: %d (%s)\n", error->error_code, msg); else fprintf(stderr, " Error: %d (%s)\n", error->error_code, error_name(error->error_code)); #endif fprintf(stderr, " Major opcode of failed request: %d (%s)\n", error->request_code, request_name(error->request_code)); fprintf(stderr, " Minor opcode of failed request: %d \n", error->minor_code); /* error->resourceid may be uninitialised. This is no proble since we * are dumping core anyway. */ fprintf(stderr, " Resource id of failed request: 0x%lx \n", error->resourceid); /* leave a coredump */ do_coredump(); } #ifndef USE_GET_ERROR_TEXT /* this comes out of X.h */ static char *error_names[] = { "BadRequest", "BadValue", "BadWindow", "BadPixmap", "BadAtom", "BadCursor", "BadFont", "BadMatch", "BadDrawable", "BadAccess", "BadAlloc", "BadColor", "BadGC", "BadIDChoice", "BadName", "BadLength", "BadImplementation", }; static char *error_name(unsigned char code) { if (code == 0 || code > (sizeof(error_names) / sizeof(char *))) { sprintf(unknown, "Unknown: %d", (int)code); return unknown; } return error_names[code - 1]; } #endif /* this comes out of Xproto.h */ static char *code_names[] = { "CreateWindow", "ChangeWindowAttributes", "GetWindowAttributes", "DestroyWindow", "DestroySubwindows", "ChangeSaveSet", "ReparentWindow", "MapWindow", "MapSubwindows", "UnmapWindow", "UnmapSubwindows", "ConfigureWindow", "CirculateWindow", "GetGeometry", "QueryTree", "InternAtom", "GetAtomName", "ChangeProperty", "DeleteProperty", "GetProperty", "ListProperties", "SetSelectionOwner", "GetSelectionOwner", "ConvertSelection", "SendEvent", "GrabPointer", "UngrabPointer", "GrabButton", "UngrabButton", "ChangeActivePointerGrab", "GrabKeyboard", "UngrabKeyboard", "GrabKey", "UngrabKey", "AllowEvents", "GrabServer", "UngrabServer", "QueryPointer", "GetMotionEvents", "TranslateCoords", "WarpPointer", "SetInputFocus", "GetInputFocus", "QueryKeymap", "OpenFont", "CloseFont", "QueryFont", "QueryTextExtents", "ListFonts", "ListFontsWithInfo", "SetFontPath", "GetFontPath", "CreatePixmap", "FreePixmap", "CreateGC", "ChangeGC", "CopyGC", "SetDashes", "SetClipRectangles", "FreeGC", "ClearArea", "CopyArea", "CopyPlane", "PolyPoint", "PolyLine", "PolySegment", "PolyRectangle", "PolyArc", "FillPoly", "PolyFillRectangle", "PolyFillArc", "PutImage", "GetImage", "PolyText", "PolyText1", "ImageText", "ImageText1", "CreateColormap", "FreeColormap", "CopyColormapAndFree", "InstallColormap", "UninstallColormap", "ListInstalledColormaps", "AllocColor", "AllocNamedColor", "AllocColorCells", "AllocColorPlanes", "FreeColors", "StoreColors", "StoreNamedColor", "QueryColors", "LookupColor", "CreateCursor", "CreateGlyphCursor", "FreeCursor", "RecolorCursor", "QueryBestSize", "QueryExtension", "ListExtensions", "ChangeKeyboardMapping", "GetKeyboardMapping", "ChangeKeyboardControl", "GetKeyboardControl", "Bell", "ChangePointerControl", "GetPointerControl", "SetScreenSaver", "GetScreenSaver", "ChangeHosts", "ListHosts", "SetAccessControl", "SetCloseDownMode", "KillClient", "RotateProperties", "ForceScreenSaver", "SetPointerMapping", "GetPointerMapping", "SetModifierMapping", "GetModifierMapping", }; static char *request_name(unsigned char code) { if (code == 0 || code > (sizeof(code_names) / sizeof(char *))) { if (code == FRenderGetMajorOpCode()) { sprintf(unknown, "XRender"); } else { sprintf(unknown, "Unknown: %d", (int)code); } return unknown; } return code_names[code - 1]; } /* -------------------------- error handler stack -------------------------- */ static ferror_handler_t old_handler = NULL; void ferror_set_temp_error_handler(ferror_handler_t new_handler) { if (old_handler != NULL) { do_coredump(); } old_handler = XSetErrorHandler(old_handler); return; } void ferror_reset_temp_error_handler(void) { if (old_handler == NULL) { do_coredump(); } XSetErrorHandler(old_handler); old_handler = NULL; return; } int ferror_call_next_error_handler(Display *dpy, XErrorEvent *error) { int rc; if (old_handler == NULL) { do_coredump(); } rc = old_handler(dpy, error); return rc; }