Annotation of micropolis/src/tk/tkerror.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * tkError.c --
                      3:  *
                      4:  *     This file provides a high-performance mechanism for
                      5:  *     selectively dealing with errors that occur in talking
                      6:  *     to the X server.  This is useful, for example, when
                      7:  *     communicating with a window that may not exist.
                      8:  *
                      9:  * Copyright 1990 Regents of the University of California.
                     10:  * Permission to use, copy, modify, and distribute this
                     11:  * software and its documentation for any purpose and without
                     12:  * fee is hereby granted, provided that the above copyright
                     13:  * notice appear in all copies.  The University of California
                     14:  * makes no representations about the suitability of this
                     15:  * software for any purpose.  It is provided "as is" without
                     16:  * express or implied warranty.
                     17:  */
                     18: 
                     19: #ifndef lint
                     20: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkError.c,v 1.10 92/04/12 17:02:08 ouster Exp $ SPRITE (Berkeley)";
                     21: #endif
                     22: 
                     23: #include "tkconfig.h"
                     24: #include "tkint.h"
                     25: 
                     26: static initialized = 0;
                     27: 
                     28: /*
                     29:  * Forward references to procedures declared later in this file:
                     30:  */
                     31: 
                     32: static int     ErrorProc _ANSI_ARGS_((Display *display,
                     33:                    XErrorEvent *errEventPtr));
                     34: 
                     35: /*
                     36:  *--------------------------------------------------------------
                     37:  *
                     38:  * Tk_CreateErrorHandler --
                     39:  *
                     40:  *     Arrange for all a given procedure to be invoked whenever
                     41:  *     certain errors occur.
                     42:  *
                     43:  * Results:
                     44:  *     The return value is a token identifying the handler;
                     45:  *     it must be passed to Tk_DeleteErrorHandler to delete the
                     46:  *     handler.
                     47:  *
                     48:  * Side effects:
                     49:  *     If an X error occurs that matches the error, request,
                     50:  *     and minor arguments, then errorProc will be invoked.
                     51:  *     ErrorProc should have the following structure:
                     52:  *
                     53:  *     int
                     54:  *     errorProc(clientData, errorEventPtr)
                     55:  *         caddr_t clientData;
                     56:  *         XErrorEvent *errorEventPtr;
                     57:  *     {
                     58:  *     }
                     59:  *
                     60:  *     The clientData argument will be the same as the clientData
                     61:  *     argument to this procedure, and errorEvent will describe
                     62:  *     the error.  If errorProc returns 0, it means that it
                     63:  *     completely "handled" the error:  no further processing
                     64:  *     should be done.  If errorProc returns 1, it means that it
                     65:  *     didn't know how to deal with the error, so we should look
                     66:  *     for other error handlers, or invoke the default error
                     67:  *     handler if no other handler returns zero.  Handlers are
                     68:  *     invoked in order of age:  youngest handler first.
                     69:  *
                     70:  *     Note:  errorProc will only be called for errors associated
                     71:  *     with X requests made AFTER this call, but BEFORE the handler
                     72:  *     is deleted by calling Tk_DeleteErrorHandler.
                     73:  *
                     74:  *--------------------------------------------------------------
                     75:  */
                     76: 
                     77: Tk_ErrorHandler
                     78: Tk_CreateErrorHandler(display, error, request, minorCode, errorProc, clientData)
                     79:     Display *display;          /* Display for which to handle
                     80:                                 * errors. */
                     81:     int error;                 /* Consider only errors with this
                     82:                                 * error_code (-1 means consider
                     83:                                 * all errors). */
                     84:     int request;               /* Consider only errors with this
                     85:                                 * major request code (-1 means
                     86:                                 * consider all major codes). */
                     87:     int minorCode;             /* Consider only errors with this
                     88:                                 * minor request code (-1 means
                     89:                                 * consider all minor codes). */
                     90:     Tk_ErrorProc *errorProc;   /* Procedure to invoke when a
                     91:                                 * matching error occurs.  NULL means
                     92:                                 * just ignore matching errors. */
                     93:     ClientData clientData;     /* Arbitrary value to pass to
                     94:                                 * errorProc. */
                     95: {
                     96:     register TkErrorHandler *errorPtr;
                     97:     register TkDisplay *dispPtr;
                     98: 
                     99:     /*
                    100:      * Make sure that X calls us whenever errors occur.
                    101:      */
                    102: 
                    103:     if (!initialized) {
                    104:        XSetErrorHandler(ErrorProc);
                    105:        initialized = 1;
                    106:     }
                    107: 
                    108:     /*
                    109:      * Find the display.  If Tk doesn't know about this display,
                    110:      * it's an error:  panic.
                    111:      */
                    112: 
                    113:     for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
                    114:        if (dispPtr->display == display) {
                    115:            break;
                    116:        }
                    117:        if (dispPtr == NULL) {
                    118:            panic("Unknown display passed to Tk_CreateErrorHandler");
                    119:        }
                    120:     }
                    121: 
                    122:     /*
                    123:      * Create the handler record.
                    124:      */
                    125: 
                    126:     errorPtr = (TkErrorHandler *) ckalloc(sizeof(TkErrorHandler));
                    127:     errorPtr->dispPtr = dispPtr;
                    128:     errorPtr->firstRequest = NextRequest(display);
                    129:     errorPtr->lastRequest = -1;
                    130:     errorPtr->error = error;
                    131:     errorPtr->request = request;
                    132:     errorPtr->minorCode = minorCode;
                    133:     errorPtr->errorProc = errorProc;
                    134:     errorPtr->clientData = clientData;
                    135:     errorPtr->nextPtr = dispPtr->errorPtr;
                    136:     dispPtr->errorPtr = errorPtr;
                    137: 
                    138:     return (Tk_ErrorHandler) errorPtr;
                    139: }
                    140: 
                    141: /*
                    142:  *--------------------------------------------------------------
                    143:  *
                    144:  * Tk_DeleteErrorHandler --
                    145:  *
                    146:  *     Do not use an error handler anymore.
                    147:  *
                    148:  * Results:
                    149:  *     None.
                    150:  *
                    151:  * Side effects:
                    152:  *     The handler denoted by the "handler" argument will not
                    153:  *     be invoked for any X errors associated with requests
                    154:  *     made after this call.  However, if errors arrive later
                    155:  *     for requests made BEFORE this call, then the handler
                    156:  *     will still be invoked.  Call XSync if you want to be
                    157:  *     sure that all outstanding errors have been received
                    158:  *     and processed.
                    159:  *
                    160:  *--------------------------------------------------------------
                    161:  */
                    162: 
                    163: void
                    164: Tk_DeleteErrorHandler(handler)
                    165:     Tk_ErrorHandler handler;   /* Token for handler to delete;
                    166:                                 * was previous return value from
                    167:                                 * Tk_CreateErrorHandler. */
                    168: {
                    169:     register TkErrorHandler *errorPtr = (TkErrorHandler *) handler;
                    170:     register TkDisplay *dispPtr = errorPtr->dispPtr;
                    171: 
                    172:     errorPtr->lastRequest = NextRequest(dispPtr->display) - 1;
                    173: 
                    174:     /*
                    175:      * Every once-in-a-while, cleanup handlers that are no longer
                    176:      * active.  We probably won't be able to free the handler that
                    177:      * was just deleted (need to wait for any outstanding requests to
                    178:      * be processed by server), but there may be previously-deleted
                    179:      * handlers that are now ready for garbage collection.  To reduce
                    180:      * the cost of the cleanup, let a few dead handlers pile up, then
                    181:      * clean them all at once.  This adds a bit of overhead to errors
                    182:      * that might occur while the dead handlers are hanging around,
                    183:      * but reduces the overhead of scanning the list to clean up
                    184:      * (particularly if there are many handlers that stay around
                    185:      * forever).
                    186:      */
                    187: 
                    188:     dispPtr->deleteCount += 1;
                    189:     if (dispPtr->deleteCount >= 10) {
                    190:        register TkErrorHandler *prevPtr;
                    191:        TkErrorHandler *nextPtr;
                    192:        int lastSerial;
                    193: 
                    194:        dispPtr->deleteCount = 0;
                    195:        lastSerial = LastKnownRequestProcessed(dispPtr->display);
                    196:        errorPtr = dispPtr->errorPtr;
                    197:        for (errorPtr = dispPtr->errorPtr, prevPtr = NULL;
                    198:                errorPtr != NULL;  errorPtr = nextPtr) {
                    199:            nextPtr = errorPtr->nextPtr;
                    200:            if ((errorPtr->lastRequest != -1)
                    201:                    && (errorPtr->lastRequest <= lastSerial)) {
                    202:                if (prevPtr == NULL) {
                    203:                    dispPtr->errorPtr = nextPtr;
                    204:                } else {
                    205:                    prevPtr->nextPtr = nextPtr;
                    206:                }
                    207:                ckfree((char *) errorPtr);
                    208:                continue;
                    209:            }
                    210:            prevPtr = errorPtr;
                    211:        }
                    212:     }
                    213: }
                    214: 
                    215: /*
                    216:  *--------------------------------------------------------------
                    217:  *
                    218:  * ErrorProc --
                    219:  *
                    220:  *     This procedure is invoked by the X system when error
                    221:  *     events arrive.
                    222:  *
                    223:  * Results:
                    224:  *     If it returns, the return value is zero.  However,
                    225:  *     it is possible that one of the error handlers may
                    226:  *     just exit.
                    227:  *
                    228:  * Side effects:
                    229:  *     This procedure does two things.  First, it uses the
                    230:  *     serial #  in the error event to eliminate handlers whose
                    231:  *     expiration serials are now in the past.  Second, it
                    232:  *     invokes any handlers that want to deal with the error.
                    233:  *
                    234:  *--------------------------------------------------------------
                    235:  */
                    236: 
                    237: static int
                    238: ErrorProc(display, errEventPtr)
                    239:     Display *display;                  /* Display for which error
                    240:                                         * occurred. */
                    241:     register XErrorEvent *errEventPtr; /* Information about error. */
                    242: {
                    243:     register TkDisplay *dispPtr;
                    244:     register TkErrorHandler *errorPtr;
                    245:     extern int _XDefaultError();
                    246: 
                    247:     /*
                    248:      * See if we know anything about the display.  If not, then
                    249:      * invoke the default error handler.
                    250:      */
                    251: 
                    252:     for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
                    253:        if (dispPtr == NULL) {
                    254:            goto couldntHandle;
                    255:        }
                    256:        if (dispPtr->display == display) {
                    257:            break;
                    258:        }
                    259:     }
                    260: 
                    261:     /*
                    262:      * Otherwise invoke any relevant handlers for the error, in order.
                    263:      */
                    264: 
                    265:     for (errorPtr = dispPtr->errorPtr; errorPtr != NULL;
                    266:            errorPtr = errorPtr->nextPtr) {
                    267:        if ((errorPtr->firstRequest > errEventPtr->serial)
                    268:                || ((errorPtr->error != -1)
                    269:                    && (errorPtr->error != errEventPtr->error_code))
                    270:                || ((errorPtr->request != -1)
                    271:                    && (errorPtr->request != errEventPtr->request_code))
                    272:                || ((errorPtr->minorCode != -1)
                    273:                    && (errorPtr->minorCode != errEventPtr->minor_code))
                    274:                || ((errorPtr->lastRequest != -1)
                    275:                    && (errorPtr->lastRequest < errEventPtr->serial))) {
                    276:            continue;
                    277:        }
                    278:        if (errorPtr->errorProc == NULL) {
                    279:            return 0;
                    280:        } else {
                    281:            if ((*errorPtr->errorProc)(errorPtr->clientData,
                    282:                    errEventPtr) == 0) {
                    283:                return 0;
                    284:            }
                    285:        }
                    286:     }
                    287: 
                    288:     /*
                    289:      * We couldn't handle the error.  Use the default handler.
                    290:      */
                    291: 
                    292:     couldntHandle:
                    293:     return _XDefaultError(display, errEventPtr);
                    294: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.