Changeset 2079
- Timestamp:
- Jun 26, 2005, 5:48:49 AM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/emx/src/lib/sys/libcfork.c
-
Property cvs2svn:cvs-rev
changed from
1.12
to1.13
r2078 r2079 81 81 82 82 83 /** 84 * Exception handler registration record for the parent process. 85 */ 86 typedef 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! */ 100 static volatile __LIBC_PFORKHANDLE g_pForkHandle = NULL; 101 83 102 84 103 /******************************************************************************* … … 120 139 static int forkPrmCompletionCallback(__LIBC_PFORKHANDLE pForkHandle, __LIBC_PFNCOMPLETIONCALLBACK pfnCallback, void *pvArg, __LIBC_FORKCTX enmContext); 121 140 static __LIBC_PFORKMODULE forkBthGetModules(void); 122 static void forkChlFatalError(__LIBC_PFORKHANDLE pForkHandle, int rc) __attribute__((__noreturn__));123 141 static int forkBthProcessModules(__LIBC_PFORKHANDLE pForkHandle, __LIBC_PFORKMODULE pModules, __LIBC_FORKOP enmOperation); 124 142 static int forkBthBufferGive(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKCTX enmCtx); … … 137 155 static int forkBthCallbacksCall(__LIBC_PFORKCALLBACK *papCallbacks, __LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation); 138 156 static void forkBthDumpMemFlags(void *pv); 157 static void forkChlFatalError(__LIBC_PFORKHANDLE pForkHandle, int rc) __attribute__((__noreturn__)); 158 static ULONG _System forkChlExceptionHandler(PEXCEPTIONREPORTRECORD pXcptRepRec, 159 PEXCEPTIONREGISTRATIONRECORD pXcptRegRec, 160 PCONTEXTRECORD pCtx, 161 PVOID pvWhatEver); 162 static ULONG _System forkParExceptionHandler(PEXCEPTIONREPORTRECORD pXcptRepRec, 163 PEXCEPTIONREGISTRATIONRECORD pXcptRegRec, 164 PCONTEXTRECORD pCtx, 165 PVOID pvWhatEver); 139 166 140 167 … … 201 228 __LIBC_PSPMPROCESS pProcess; 202 229 __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; 203 241 204 242 #ifdef TIMEBOMB … … 222 260 DosExit(EXIT_PROCESS, /*fixme*/0xffff); 223 261 } 262 pTib->tib_pexchain = XcptRegRec.prev_structure; 224 263 LIBCLOG_RETURN_INT(-1); 225 264 } … … 270 309 #endif 271 310 if (!pProcess->pvForkHandle) 311 { 312 pTib->tib_pexchain = XcptRegRec.prev_structure; 272 313 LIBCLOG_RETURN_INT(0); 314 } 273 315 /* we are! */ 274 316 … … 284 326 DosExit(EXIT_PROCESS, /*fixme*/0xffff); 285 327 } 328 pTib->tib_pexchain = XcptRegRec.prev_structure; 286 329 LIBCLOG_RETURN_INT(-1); 287 330 } 331 g_pForkHandle = pForkHandle; 288 332 289 333 /* … … 298 342 DosExit(EXIT_PROCESS, /*fixme*/0xffff); 299 343 } 344 pTib->tib_pexchain = XcptRegRec.prev_structure; 300 345 LIBCLOG_RETURN_INT(-1); 301 346 } … … 305 350 */ 306 351 LIBC_ASSERT(!fExecutable); 352 pTib->tib_pexchain = XcptRegRec.prev_structure; 307 353 LIBCLOG_RETURN_INT(1); 308 354 } … … 341 387 int rc; 342 388 pid_t pid = -1; 389 PTIB pTib; 390 PPIB pPib; 391 __LIBC_FORKXCPTREGREC XcptRegRec; 392 FS_VAR(); 343 393 344 394 /* … … 370 420 371 421 /* 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 /* 372 433 * 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); 375 437 if (pForkHandle) 376 438 { … … 411 473 if (rc < 0) 412 474 { 413 FS_VAR();414 FS_SAVE_LOAD();415 475 RESULTCODES resc; 416 476 PID pibReaped; 417 477 DosWaitChild(DCWA_PROCESS,DCWW_NOWAIT, &resc, &pibReaped, pid); 418 FS_RESTORE();419 478 } 420 479 } … … 424 483 * Process child context completion callbacks. 425 484 */ 426 forkParCompletionParent(pForkHandle, rc); 485 if (!XcptRegRec.fDoneCompletion) 486 forkParCompletionParent(pForkHandle, rc); 427 487 forkBthCloseHandle(pForkHandle, __LIBC_FORK_CTX_PARENT); 428 488 } … … 435 495 __libc_back_processWaitNotifyExec(pid); 436 496 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; 437 502 _fmutex_release(&__libc_gmtxExec); 503 FS_RESTORE(); 438 504 if (rc >= 0) 439 505 LIBCLOG_RETURN_INT(pid); … … 1027 1093 int rc; 1028 1094 __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 1029 1108 /* 1030 1109 * The __LIBC_FORK_OP_EXEC_CHILD run is complete, … … 1080 1159 LIBC_ASSERTM(pProcess, "No self process!!!\n"); 1081 1160 pProcess->pvForkHandle = NULL; 1082 1161 1083 1162 /* 1084 1163 * The return here will go back to the inline assmebly which called us … … 1087 1166 _fmutex_release(&__libc_gmtxExec); 1088 1167 __libc_spmExeInited(); 1168 pTib->tib_pexchain = END_OF_CHAIN; 1089 1169 LIBCLOG_RETURN_INT(0); 1090 1170 } … … 1200 1280 if (rc >= 0) 1201 1281 rc = forkBthBufferWait(pForkHandle, __LIBC_FORK_CTX_CHILD); 1202 if (rc < 0 )1282 if (rc < 0 && pForkHandle->pidChild > 0) 1203 1283 DosKillProcess(DKP_PROCESS, pForkHandle->pidChild); /** @todo move me into the above functions? */ 1204 1284 … … 1284 1364 * Close the semaphores and free the memory. 1285 1365 */ 1366 g_pForkHandle = NULL; 1286 1367 rc = DosCloseEventSem(pForkHandle->hevChild); 1287 1368 LIBC_ASSERTM(!rc, "DosCloseEventSem(%lx) failed rc=%d (child)\n", pForkHandle->hevChild, rc); … … 1738 1819 1739 1820 /** 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 else1787 {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 /**1811 1821 * Process a module list calling the pfnAtFork() callback with a given operation. 1812 1822 * … … 2008 2018 LIBCLOG_MSG("ABORT err=%d\n", pHdr->u.Abort.err); 2009 2019 rc = pHdr->u.Abort.err; 2020 if (enmCtx == __LIBC_FORK_CTX_CHILD) 2021 forkChlFatalError(pForkHandle, rc); 2010 2022 break; 2011 2023 … … 2492 2504 } 2493 2505 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 */ 2513 void 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 */ 2589 static 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 */ 2710 static 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 -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.