Changeset 2079


Ignore:
Timestamp:
Jun 26, 2005, 5:48:49 AM (20 years ago)
Author:
bird
Message:

Fixed SIGINT and similar issues with fork(). LIBC emulated kill() won't work right.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/emx/src/lib/sys/libcfork.c

    • Property cvs2svn:cvs-rev changed from 1.12 to 1.13
    r2078 r2079  
    8181
    8282
     83/**
     84 * Exception handler registration record for the parent process.
     85 */
     86typedef struct __LIBC_FORKXCPTREGREC
     87{
     88    /** The exception registration record. */
     89    EXCEPTIONREGISTRATIONRECORD Core;
     90    /** Indicator set by the exception handler if it did the completion handlers. */
     91    volatile int                fDoneCompletion;
     92} __LIBC_FORKXCPTREGREC, *__LIBC_PFORKXCPTREGREC;
     93
     94
     95/*******************************************************************************
     96*   Global Variables                                                           *
     97*******************************************************************************/
     98/** Pointer to the forkhandle for the current fork operation.
     99 * This is *only* used by the exception and signal handlers! */
     100static volatile __LIBC_PFORKHANDLE g_pForkHandle = NULL;
     101
    83102
    84103/*******************************************************************************
     
    120139static int                  forkPrmCompletionCallback(__LIBC_PFORKHANDLE pForkHandle, __LIBC_PFNCOMPLETIONCALLBACK pfnCallback, void *pvArg, __LIBC_FORKCTX enmContext);
    121140static __LIBC_PFORKMODULE   forkBthGetModules(void);
    122 static void                 forkChlFatalError(__LIBC_PFORKHANDLE pForkHandle, int rc) __attribute__((__noreturn__));
    123141static int                  forkBthProcessModules(__LIBC_PFORKHANDLE pForkHandle, __LIBC_PFORKMODULE pModules, __LIBC_FORKOP enmOperation);
    124142static int                  forkBthBufferGive(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKCTX enmCtx);
     
    137155static int                  forkBthCallbacksCall(__LIBC_PFORKCALLBACK *papCallbacks, __LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation);
    138156static void                 forkBthDumpMemFlags(void *pv);
     157static void                 forkChlFatalError(__LIBC_PFORKHANDLE pForkHandle, int rc) __attribute__((__noreturn__));
     158static ULONG _System        forkChlExceptionHandler(PEXCEPTIONREPORTRECORD       pXcptRepRec,
     159                                                    PEXCEPTIONREGISTRATIONRECORD pXcptRegRec,
     160                                                    PCONTEXTRECORD               pCtx,
     161                                                    PVOID                        pvWhatEver);
     162static ULONG _System        forkParExceptionHandler(PEXCEPTIONREPORTRECORD       pXcptRepRec,
     163                                                    PEXCEPTIONREGISTRATIONRECORD pXcptRegRec,
     164                                                    PCONTEXTRECORD               pCtx,
     165                                                    PVOID                        pvWhatEver);
    139166
    140167
     
    201228    __LIBC_PSPMPROCESS  pProcess;
    202229    __LIBC_PFORKHANDLE  pForkHandle;
     230    PTIB                pTib;
     231    PPIB                pPib;
     232    EXCEPTIONREGISTRATIONRECORD XcptRegRec;
     233
     234    /*
     235     * Install exceptionhandler.
     236     */
     237    DosGetInfoBlocks(&pTib, &pPib);
     238    XcptRegRec.ExceptionHandler = forkChlExceptionHandler;
     239    XcptRegRec.prev_structure = pTib->tib_pexchain;
     240    pTib->tib_pexchain = &XcptRegRec;
    203241
    204242#ifdef TIMEBOMB
     
    222260            DosExit(EXIT_PROCESS, /*fixme*/0xffff);
    223261        }
     262        pTib->tib_pexchain = XcptRegRec.prev_structure;
    224263        LIBCLOG_RETURN_INT(-1);
    225264    }
     
    270309#endif
    271310    if (!pProcess->pvForkHandle)
     311    {
     312        pTib->tib_pexchain = XcptRegRec.prev_structure;
    272313        LIBCLOG_RETURN_INT(0);
     314    }
    273315    /* we are! */
    274316
     
    284326            DosExit(EXIT_PROCESS, /*fixme*/0xffff);
    285327        }
     328        pTib->tib_pexchain = XcptRegRec.prev_structure;
    286329        LIBCLOG_RETURN_INT(-1);
    287330    }
     331    g_pForkHandle = pForkHandle;
    288332
    289333    /*
     
    298342            DosExit(EXIT_PROCESS, /*fixme*/0xffff);
    299343        }
     344        pTib->tib_pexchain = XcptRegRec.prev_structure;
    300345        LIBCLOG_RETURN_INT(-1);
    301346    }
     
    305350     */
    306351    LIBC_ASSERT(!fExecutable);
     352    pTib->tib_pexchain = XcptRegRec.prev_structure;
    307353    LIBCLOG_RETURN_INT(1);
    308354}
     
    341387    int                 rc;
    342388    pid_t               pid = -1;
     389    PTIB                pTib;
     390    PPIB                pPib;
     391    __LIBC_FORKXCPTREGREC XcptRegRec;
     392    FS_VAR();
    343393
    344394    /*
     
    370420
    371421    /*
     422     * Register the exception handler.
     423     */
     424    FS_SAVE_LOAD();
     425    DosGetInfoBlocks(&pTib, &pPib);
     426    XcptRegRec.fDoneCompletion = 0;
     427    XcptRegRec.Core.ExceptionHandler = forkParExceptionHandler;
     428    XcptRegRec.Core.prev_structure = pTib->tib_pexchain;
     429    pTib->tib_pexchain = &XcptRegRec.Core;
     430    g_pForkHandle = NULL;
     431
     432    /*
    372433     * Allocate and initialize the memory for the fork handle.
    373      */
    374     pForkHandle = forkParAllocHandle(pModules, pvStackRet, pvForkRet);
     434     * Install signal handlers after that.
     435     */
     436    g_pForkHandle = pForkHandle = forkParAllocHandle(pModules, pvStackRet, pvForkRet);
    375437    if (pForkHandle)
    376438    {
     
    411473                if (rc < 0)
    412474                {
    413                     FS_VAR();
    414                     FS_SAVE_LOAD();
    415475                    RESULTCODES resc;
    416476                    PID         pibReaped;
    417477                    DosWaitChild(DCWA_PROCESS,DCWW_NOWAIT, &resc, &pibReaped, pid);
    418                     FS_RESTORE();
    419478                }
    420479            }
     
    424483         * Process child context completion callbacks.
    425484         */
    426         forkParCompletionParent(pForkHandle, rc);
     485        if (!XcptRegRec.fDoneCompletion)
     486            forkParCompletionParent(pForkHandle, rc);
    427487        forkBthCloseHandle(pForkHandle, __LIBC_FORK_CTX_PARENT);
    428488    }
     
    435495        __libc_back_processWaitNotifyExec(pid);
    436496
     497    /*
     498     * Reregister the exception handler but now replacing the existing chain.
     499     */
     500    pTib->tib_pexchain = XcptRegRec.Core.prev_structure;
     501    g_pForkHandle = NULL;
    437502    _fmutex_release(&__libc_gmtxExec);
     503    FS_RESTORE();
    438504    if (rc >= 0)
    439505        LIBCLOG_RETURN_INT(pid);
     
    10271093    int                 rc;
    10281094    __LIBC_PFORKMODULE  pModules;
     1095    PTIB                pTib;
     1096    PPIB                pPib;
     1097    EXCEPTIONREGISTRATIONRECORD XcptRegRec;
     1098
     1099    /*
     1100     * Reregister the exception handler but now replacing the existing chain.
     1101     */
     1102    DosGetInfoBlocks(&pTib, &pPib);
     1103    XcptRegRec.prev_structure = END_OF_CHAIN;
     1104    XcptRegRec.ExceptionHandler = forkChlExceptionHandler;
     1105    pTib->tib_pexchain = &XcptRegRec;
     1106    g_pForkHandle = pForkHandle;
     1107
    10291108    /*
    10301109     * The __LIBC_FORK_OP_EXEC_CHILD run is complete,
     
    10801159    LIBC_ASSERTM(pProcess, "No self process!!!\n");
    10811160    pProcess->pvForkHandle = NULL;
    1082    
     1161
    10831162    /*
    10841163     * The return here will go back to the inline assmebly which called us
     
    10871166    _fmutex_release(&__libc_gmtxExec);
    10881167    __libc_spmExeInited();
     1168    pTib->tib_pexchain = END_OF_CHAIN;
    10891169    LIBCLOG_RETURN_INT(0);
    10901170}
     
    12001280    if (rc >= 0)
    12011281        rc = forkBthBufferWait(pForkHandle, __LIBC_FORK_CTX_CHILD);
    1202     if (rc < 0)
     1282    if (rc < 0 && pForkHandle->pidChild > 0)
    12031283        DosKillProcess(DKP_PROCESS, pForkHandle->pidChild); /** @todo move me into the above functions? */
    12041284
     
    12841364     * Close the semaphores and free the memory.
    12851365     */
     1366    g_pForkHandle = NULL;
    12861367    rc = DosCloseEventSem(pForkHandle->hevChild);
    12871368    LIBC_ASSERTM(!rc, "DosCloseEventSem(%lx) failed rc=%d (child)\n", pForkHandle->hevChild, rc);
     
    17381819
    17391820/**
    1740  * Aborts the fork operation from the child side.
    1741  *
    1742  * @param   pForkHandle     Pointer to fork handle.
    1743  * @param   rc              The return code (negative) which caused the failure.
    1744  */
    1745 void                 forkChlFatalError(__LIBC_PFORKHANDLE pForkHandle, int rc)
    1746 {
    1747     LIBCLOG_ENTER("pForkHandle=%p rc=%d\n", (void *)pForkHandle, rc);
    1748     static const char   szMsg[] = "LIBC Error: Child Aborting fork()!\r\n";
    1749     ULONG               cbWritten;
    1750     PID                 pid;
    1751     TID                 tid;
    1752     ULONG               cNesting;
    1753     PPIB                pPib;
    1754     PTIB                pTib;
    1755     int                 rc2;
    1756 __asm__ __volatile__("int3\n\t");
    1757 
    1758     /*
    1759      * Completion callbacks.
    1760      */
    1761     forkChlCompletionChild(pForkHandle, rc);
    1762 
    1763     /*
    1764      * Who owns the buffer?
    1765      */
    1766     DosGetInfoBlocks(&pTib, &pPib);
    1767     rc2 = DosQueryMutexSem(pForkHandle->hmtx, &pid, &tid, &cNesting);
    1768     /* if we don't, let's try grab it quickly. */
    1769     if (!rc2 && (pid != pPib->pib_ulpid || tid != 1))
    1770     {
    1771         DosRequestMutexSem(pForkHandle->hmtx, 50);
    1772         rc2 = DosQueryMutexSem(pForkHandle->hmtx, &pid, &tid, &cNesting);
    1773     }
    1774     if (!rc2 && pid == pPib->pib_ulpid && tid == 1)
    1775     {
    1776         /*
    1777          * Empty the fork buffer, add abort and end, give buffer to parent.
    1778          */
    1779         LIBCLOG_MSG("Making abort packet with err=%d.\n", rc);
    1780         forkBthBufferReset(pForkHandle);
    1781         forkBthBufferAbort(pForkHandle, rc);
    1782         forkBthBufferEnd(pForkHandle);
    1783         forkBthBufferGive(pForkHandle, __LIBC_FORK_CTX_CHILD);
    1784         LIBCLOG_MSG("Abort packet sent.\n");
    1785     }
    1786     else
    1787     {
    1788         /* mmm... eer.. yea... I think we'll just quit for now. */
    1789         LIBCLOG_MSG("Cannot send abort packet, not buffer owner.\n");
    1790         /** @todo think out a safe way of flagging this to prevent having to timeout! */
    1791     }
    1792 
    1793     /*
    1794      * Free the fork handle.
    1795      */
    1796     forkBthCloseHandle(pForkHandle, __LIBC_FORK_CTX_CHILD);
    1797 
    1798     /*
    1799      * Exit process.
    1800      */
    1801     DosWrite(2, szMsg, sizeof(szMsg) - 1, &cbWritten);
    1802     for (;;)
    1803     {
    1804         LIBCLOG_MSG("Calling DosExit(EXIT_PROCESS, 0xffff)...\n");
    1805         DosExit(EXIT_PROCESS, /*fixme*/0xffff);
    1806     }
    1807 }
    1808 
    1809 
    1810 /**
    18111821 * Process a module list calling the pfnAtFork() callback with a given operation.
    18121822 *
     
    20082018                LIBCLOG_MSG("ABORT err=%d\n", pHdr->u.Abort.err);
    20092019                rc = pHdr->u.Abort.err;
     2020                if (enmCtx == __LIBC_FORK_CTX_CHILD)
     2021                    forkChlFatalError(pForkHandle, rc);
    20102022                break;
    20112023
     
    24922504}
    24932505
     2506
     2507/**
     2508 * Aborts the fork operation from the child side.
     2509 *
     2510 * @param   pForkHandle     Pointer to fork handle.
     2511 * @param   rc              The return code (negative) which caused the failure.
     2512 */
     2513void                 forkChlFatalError(__LIBC_PFORKHANDLE pForkHandle, int rc)
     2514{
     2515    LIBCLOG_ENTER("pForkHandle=%p rc=%d\n", (void *)pForkHandle, rc);
     2516    static const char   szMsg[] = "LIBC Error: Child aborting fork()!\r\n";
     2517    ULONG               cbWritten;
     2518    PID                 pid;
     2519    TID                 tid;
     2520    ULONG               cNesting;
     2521    PPIB                pPib;
     2522    PTIB                pTib;
     2523    int                 rc2;
     2524/*__asm__ __volatile__("int3\n\t");*/
     2525
     2526    /*
     2527     * Completion callbacks.
     2528     */
     2529    forkChlCompletionChild(pForkHandle, rc);
     2530
     2531    /*
     2532     * Who owns the buffer?
     2533     */
     2534    DosGetInfoBlocks(&pTib, &pPib);
     2535    rc2 = DosQueryMutexSem(pForkHandle->hmtx, &pid, &tid, &cNesting);
     2536    /* if we don't, let's try grab it quickly. */
     2537    if (!rc2 && (pid != pPib->pib_ulpid || tid != 1))
     2538    {
     2539        DosRequestMutexSem(pForkHandle->hmtx, 50);
     2540        rc2 = DosQueryMutexSem(pForkHandle->hmtx, &pid, &tid, &cNesting);
     2541    }
     2542    if (!rc2 && pid == pPib->pib_ulpid && tid == 1)
     2543    {
     2544        /*
     2545         * Empty the fork buffer, add abort and end, give buffer to parent.
     2546         */
     2547        LIBCLOG_MSG("Making abort packet with err=%d.\n", rc);
     2548        forkBthBufferReset(pForkHandle);
     2549        forkBthBufferAbort(pForkHandle, rc);
     2550        forkBthBufferEnd(pForkHandle);
     2551        forkBthBufferGive(pForkHandle, __LIBC_FORK_CTX_CHILD);
     2552        DosSleep(1);
     2553        LIBCLOG_MSG("Abort packet sent.\n");
     2554    }
     2555    else
     2556    {
     2557        /* mmm... eer.. yea... I think we'll just quit for now. */
     2558        LIBCLOG_MSG("Cannot send abort packet, not buffer owner.\n");
     2559        /** @todo think out a safe way of flagging this to prevent having to timeout! */
     2560    }
     2561
     2562    /*
     2563     * Free the fork handle.
     2564     */
     2565    pForkHandle->pidChild = -1;
     2566    forkBthCloseHandle(pForkHandle, __LIBC_FORK_CTX_CHILD);
     2567
     2568    /*
     2569     * Exit process.
     2570     */
     2571    DosWrite(2, szMsg, sizeof(szMsg) - 1, &cbWritten);
     2572    for (;;)
     2573    {
     2574        LIBCLOG_MSG("Calling DosExit(EXIT_PROCESS, 0xffff)...\n");
     2575        DosExit(EXIT_PROCESS, /*fixme*/0xffff);
     2576    }
     2577}
     2578
     2579
     2580/**
     2581 * Exception handler for the parent process.
     2582 *
     2583 * @returns XCPT_CONTINUE_SEARCH or XCPT_CONTINUE_EXECUTION.
     2584 * @param   pXcptRepRec     Report record.
     2585 * @param   pXcptRegRec     Registration record.
     2586 * @param   pCtx            Context record.
     2587 * @param   pvWhatEver      Not quite sure what this is...
     2588 */
     2589static ULONG _System forkParExceptionHandler(PEXCEPTIONREPORTRECORD       pXcptRepRec,
     2590                                             PEXCEPTIONREGISTRATIONRECORD pXcptRegRec,
     2591                                             PCONTEXTRECORD               pCtx,
     2592                                             PVOID                        pvWhatEver)
     2593{
     2594    __asm__ ("cld");                    /* usual paranoia.  */
     2595
     2596    if (pXcptRepRec->fHandlerFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
     2597        return XCPT_CONTINUE_SEARCH;
     2598    LIBCLOG_MSG2("forkParExceptionHandler: ExceptionNum=%#lx eip=%#lx\n", pXcptRepRec->ExceptionNum, pCtx->ctx_RegEip);
     2599
     2600    switch (pXcptRepRec->ExceptionNum)
     2601    {
     2602        /*
     2603         * Abort the fork operation and pass the exception on.
     2604         */
     2605        case XCPT_BREAKPOINT:
     2606        case XCPT_ACCESS_VIOLATION:
     2607            if (pXcptRepRec->fHandlerFlags & EH_NESTED_CALL)
     2608                return XCPT_CONTINUE_SEARCH;
     2609        case XCPT_SIGNAL:
     2610        case XCPT_DATATYPE_MISALIGNMENT:
     2611        case XCPT_INTEGER_OVERFLOW:
     2612        case XCPT_INTEGER_DIVIDE_BY_ZERO:
     2613        case XCPT_FLOAT_DIVIDE_BY_ZERO:
     2614        case XCPT_FLOAT_OVERFLOW:
     2615        case XCPT_FLOAT_UNDERFLOW:
     2616        case XCPT_FLOAT_DENORMAL_OPERAND:
     2617        case XCPT_FLOAT_INEXACT_RESULT:
     2618        case XCPT_FLOAT_INVALID_OPERATION:
     2619        case XCPT_FLOAT_STACK_CHECK:
     2620        case XCPT_ARRAY_BOUNDS_EXCEEDED:
     2621        case XCPT_ILLEGAL_INSTRUCTION:
     2622        case XCPT_INVALID_LOCK_SEQUENCE:
     2623        case XCPT_PRIVILEGED_INSTRUCTION:
     2624        case XCPT_SINGLE_STEP:
     2625        case XCPT_ASYNC_PROCESS_TERMINATE:
     2626        case XCPT_PROCESS_TERMINATE:
     2627        {
     2628            __LIBC_PFORKHANDLE pForkHandle = g_pForkHandle;
     2629            g_pForkHandle = NULL;
     2630            if (pForkHandle)
     2631            {
     2632                PPIB    pPib;
     2633                PTIB    pTib;
     2634                PID     pid;
     2635                TID     tid;
     2636                ULONG   cNesting;
     2637                int     rc;
     2638
     2639                /*
     2640                 * Perform parent completion.
     2641                 */
     2642                DosEnterMustComplete(&cNesting); /* no signals until we're safely backed out, please. */
     2643                ((__LIBC_PFORKXCPTREGREC)pXcptRegRec)->fDoneCompletion = 1;
     2644                forkParCompletionParent(pForkHandle, -EINTR);
     2645                DosExitMustComplete(&cNesting);
     2646
     2647                /*
     2648                 * Try send an abort package if we can.
     2649                 */
     2650                DosGetInfoBlocks(&pTib, &pPib);
     2651                rc = DosQueryMutexSem(pForkHandle->hmtx, &pid, &tid, &cNesting);
     2652                /* if we don't, let's try grab it quickly. */
     2653                if (!rc && (pid != pPib->pib_ulpid || tid != pTib->tib_ptib2->tib2_ultid))
     2654                {
     2655                    DosRequestMutexSem(pForkHandle->hmtx, 50);
     2656                    rc = DosQueryMutexSem(pForkHandle->hmtx, &pid, &tid, &cNesting);
     2657                }
     2658                if (!rc && pid == pPib->pib_ulpid && tid == pTib->tib_ptib2->tib2_ultid)
     2659                {
     2660                    /*
     2661                     * Empty the fork buffer, add abort and end, give buffer to parent.
     2662                     */
     2663                    LIBCLOG_MSG2("Making abort packet with err=%d.\n", rc);
     2664                    forkBthBufferReset(pForkHandle);
     2665                    forkBthBufferAbort(pForkHandle, rc);
     2666                    forkBthBufferEnd(pForkHandle);
     2667                    forkBthBufferGive(pForkHandle, __LIBC_FORK_CTX_PARENT);
     2668                    LIBCLOG_MSG2("Abort packet sent.\n");
     2669                    DosWaitEventSem(pForkHandle->hevParent, 500);
     2670                }
     2671                else
     2672                {
     2673                    LIBCLOG_MSG2("Cannot send abort packet, not buffer owner.\n");
     2674                }
     2675
     2676                /*
     2677                 * Take evasive action.
     2678                 */
     2679                DosPostEventSem(pForkHandle->hevChild);
     2680                DosPostEventSem(pForkHandle->hevParent);
     2681                DosReleaseMutexSem(pForkHandle->hmtx);
     2682                pid = pForkHandle->pidChild;
     2683                pForkHandle->pidChild = -1;
     2684                if ((pid_t)pid > 0)
     2685                {
     2686                    RESULTCODES resc;
     2687                    PID         pibReaped;
     2688                    DosKillProcess(DKP_PROCESS, pForkHandle->pidChild);
     2689                    DosSleep(0);
     2690                    DosWaitChild(DCWA_PROCESS,DCWW_NOWAIT, &resc, &pibReaped, pid);
     2691                }
     2692            }
     2693            break;
     2694        }
     2695    }
     2696
     2697    return XCPT_CONTINUE_SEARCH;
     2698}
     2699
     2700
     2701/**
     2702 * Exception handler for the child process.
     2703 *
     2704 * @returns XCPT_CONTINUE_SEARCH or XCPT_CONTINUE_EXECUTION.
     2705 * @param   pXcptRepRec     Report record.
     2706 * @param   pXcptRegRec     Registration record.
     2707 * @param   pCtx            Context record.
     2708 * @param   pvWhatEver      Not quite sure what this is...
     2709 */
     2710static ULONG _System forkChlExceptionHandler(PEXCEPTIONREPORTRECORD       pXcptRepRec,
     2711                                             PEXCEPTIONREGISTRATIONRECORD pXcptRegRec,
     2712                                             PCONTEXTRECORD               pCtx,
     2713                                             PVOID                        pvWhatEver)
     2714{
     2715    PPIB    pPib;
     2716    PTIB    pTib;
     2717    __asm__ ("cld");                    /* usual paranoia.  */
     2718
     2719    if (pXcptRepRec->fHandlerFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
     2720        return XCPT_CONTINUE_SEARCH;
     2721
     2722    DosGetInfoBlocks(&pTib, &pPib);
     2723    pTib->tib_pexchain = END_OF_CHAIN;
     2724    LIBCLOG_MSG2("forkParExceptionHandler: ExceptionNum=%#lx eip=%#lx\n", pXcptRepRec->ExceptionNum, pCtx->ctx_RegEip);
     2725
     2726    switch (pXcptRepRec->ExceptionNum)
     2727    {
     2728        /*
     2729         * Abort the fork operation and pass the exception on.
     2730         */
     2731        case XCPT_SIGNAL:
     2732        case XCPT_ACCESS_VIOLATION:
     2733        case XCPT_DATATYPE_MISALIGNMENT:
     2734        case XCPT_INTEGER_OVERFLOW:
     2735        case XCPT_INTEGER_DIVIDE_BY_ZERO:
     2736        case XCPT_FLOAT_DIVIDE_BY_ZERO:
     2737        case XCPT_FLOAT_OVERFLOW:
     2738        case XCPT_FLOAT_UNDERFLOW:
     2739        case XCPT_FLOAT_DENORMAL_OPERAND:
     2740        case XCPT_FLOAT_INEXACT_RESULT:
     2741        case XCPT_FLOAT_INVALID_OPERATION:
     2742        case XCPT_FLOAT_STACK_CHECK:
     2743        case XCPT_ARRAY_BOUNDS_EXCEEDED:
     2744        case XCPT_ILLEGAL_INSTRUCTION:
     2745        case XCPT_INVALID_LOCK_SEQUENCE:
     2746        case XCPT_PRIVILEGED_INSTRUCTION:
     2747        case XCPT_SINGLE_STEP:
     2748        case XCPT_BREAKPOINT:
     2749        case XCPT_ASYNC_PROCESS_TERMINATE:
     2750        case XCPT_PROCESS_TERMINATE:
     2751        {
     2752            __LIBC_PFORKHANDLE pForkHandle = g_pForkHandle;
     2753            g_pForkHandle = NULL;
     2754            if (pForkHandle)
     2755            {
     2756                DosPostEventSem(pForkHandle->hevParent);
     2757                forkChlFatalError(pForkHandle, -EINTR);
     2758            }
     2759            break;
     2760        }
     2761    }
     2762
     2763    return XCPT_CONTINUE_SEARCH;
     2764}
     2765
Note: See TracChangeset for help on using the changeset viewer.