Changeset 3195 in kBuild for trunk/src/kmk/kmkbuiltin/redirect.c
- Timestamp:
- Mar 27, 2018 6:09:23 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/redirect.c
r3192 r3195 92 92 # define LIBPATHSTRICT 3 93 93 # endif 94 #endif 95 96 #ifndef KMK_BUILTIN_STANDALONE 97 extern void kmk_cache_exec_image_a(const char *); /* imagecache.c */ 94 98 #endif 95 99 … … 596 600 597 601 /** 602 * Registers the child process with a care provider or waits on it to complete. 603 * 604 * @returns 0 or non-zero success indicator or child exit code, depending on 605 * the value pfIsChildExitCode points to. 606 * @param pCtx The command execution context. 607 * @param hProcess The child process handle. 608 * @param cVerbosity The verbosity level. 609 * @param pPidSpawned Where to return the PID of the spawned child 610 * when we're inside KMK and we're return without 611 * waiting. 612 * @param pfIsChildExitCode Where to indicate whether the return exit code 613 * is from the child or from our setup efforts. 614 */ 615 static int kRedirectPostnatalCareOnWindows(PKMKBUILTINCTX pCtx, HANDLE hProcess, unsigned cVerbosity, 616 pid_t *pPidSpawned, KBOOL *pfIsChildExitCode) 617 { 618 int rcExit; 619 DWORD dwTmp; 620 621 # ifndef KMK_BUILTIN_STANDALONE 622 /* 623 * Try register the child with a childcare provider, i.e. winchildren.c 624 * or sub_proc.c. 625 */ 626 # ifndef CONFIG_NEW_WIN_CHILDREN 627 if (process_kmk_register_redirect(hProcess, pPidSpawned) == 0) 628 # else 629 if ( pPidSpawned 630 && MkWinChildCreateRedirect((intptr_t)hProcess, pPidSpawned) == 0) 631 # endif 632 { 633 if (cVerbosity > 0) 634 warnx(pCtx, "debug: spawned %d", *pPidSpawned); 635 *pfIsChildExitCode = K_FALSE; 636 return 0; 637 } 638 # ifndef CONFIG_NEW_WIN_CHILDREN 639 warn(pCtx, "sub_proc is out of slots, waiting for child..."); 640 # else 641 if (pPidSpawned) 642 warn(pCtx, "MkWinChildCreateRedirect failed..."); 643 # endif 644 # endif 645 646 /* 647 * Either the provider is outbooked or we're not in a context (like 648 * standalone) where we get help with waiting and must to it ourselves 649 */ 650 dwTmp = WaitForSingleObject(hProcess, INFINITE); 651 if (dwTmp != WAIT_OBJECT_0) 652 warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp); 653 654 if (GetExitCodeProcess(hProcess, &dwTmp)) 655 rcExit = (int)dwTmp; 656 else 657 { 658 warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError()); 659 TerminateProcess(hProcess, 127); 660 rcExit = 127; 661 } 662 663 CloseHandle(hProcess); 664 *pfIsChildExitCode = K_TRUE; 665 return rcExit; 666 } 667 668 669 /** 598 670 * Tries to locate the executable image. 599 671 * … … 665 737 666 738 return pszExecutable; 739 } 740 741 742 /** 743 * Turns the orders into input for nt_child_inject_standard_handles and 744 * winchildren.c 745 * 746 * @returns 0 on success, non-zero on failure. 747 * @param pCtx The command execution context. 748 * @param cOrders Number of file operation orders. 749 * @param paOrders The file operation orders. 750 * @param pafReplace Replace (TRUE) or leave alone (FALSE) indicator 751 * for each of the starndard handles. 752 * @param pahChild Array of standard handles for injecting into the 753 * child. Parallel to pafReplace. 754 */ 755 static int kRedirectOrderToWindowsHandles(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders, 756 BOOL pafReplace[3], HANDLE pahChild[3]) 757 { 758 int i; 759 for (i = 0; i < (int)cOrders; i++) 760 { 761 int fdTarget = paOrders[i].fdTarget; 762 assert(fdTarget >= 0 && fdTarget < 3); 763 switch (paOrders[i].enmOrder) 764 { 765 case kRedirectOrder_Open: 766 if ( (paOrders[i].fOpen & O_APPEND) 767 && lseek(paOrders[i].fdSource, 0, SEEK_END) < 0) 768 return err(pCtx, 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget); 769 /* fall thru */ 770 case kRedirectOrder_Dup: 771 pahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource); 772 if (pahChild[fdTarget] == NULL || pahChild[fdTarget] == INVALID_HANDLE_VALUE) 773 return err(pCtx, 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget); 774 break; 775 776 case kRedirectOrder_Close: 777 pahChild[fdTarget] = NULL; 778 break; 779 780 default: 781 assert(0); 782 } 783 pafReplace[fdTarget] = TRUE; 784 } 785 return 0; 667 786 } 668 787 … … 774 893 CloseHandle(ProcInfo.hThread); 775 894 *phProcess = ProcInfo.hProcess; 895 # ifndef KMK_BUILTIN_STANDALONE 896 kmk_cache_exec_image_a(pszExecutable); 897 # endif 776 898 rc = 0; 777 899 } … … 789 911 BOOL afReplace[3] = { FALSE, FALSE, FALSE }; 790 912 HANDLE ahChild[3] = { NULL, NULL, NULL }; 791 rc = 0; 792 for (i = 0; i < (int)cOrders; i++) 793 { 794 int fdTarget = paOrders[i].fdTarget; 795 assert(fdTarget >= 0 && fdTarget < 3); 796 switch (paOrders[i].enmOrder) 797 { 798 case kRedirectOrder_Open: 799 if ( (paOrders[i].fOpen & O_APPEND) 800 && lseek(paOrders[i].fdSource, 0, SEEK_END) < 0) 801 rc = err(pCtx, 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget); 802 case kRedirectOrder_Dup: 803 ahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource); 804 if (ahChild[fdTarget] == NULL || ahChild[fdTarget] == INVALID_HANDLE_VALUE) 805 rc = err(pCtx, 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget); 806 break; 807 case kRedirectOrder_Close: 808 ahChild[fdTarget] = NULL; 809 break; 810 default: 811 assert(0); 812 } 813 afReplace[fdTarget] = TRUE; 814 } 913 rc = kRedirectOrderToWindowsHandles(pCtx, cOrders, paOrders, afReplace, ahChild); 815 914 if (rc == 0) 816 915 { … … 835 934 CloseHandle(ProcInfo.hThread); 836 935 *phProcess = ProcInfo.hProcess; 936 # ifndef KMK_BUILTIN_STANDALONE 937 kmk_cache_exec_image_a(pszExecutable); 938 # endif 837 939 rc = 0; 838 940 } … … 848 950 return rc; 849 951 } 952 953 # if !defined(KMK_BUILTIN_STANDALONE) && defined(CONFIG_NEW_WIN_CHILDREN) 954 /** 955 * Pass the problem on to winchildren.c when we're on one of its workers. 956 * 957 * @returns 0 on success, non-zero on failure to create. 958 * @param pCtx The command execution context. 959 * @param pszExecutable The child process executable. 960 * @param cArgs Number of arguments. 961 * @param papszArgs The child argument vector. 962 * @param papszEnvVars The child environment vector. 963 * @param pszCwd The current working directory of the child. 964 * @param cOrders Number of file operation orders. 965 * @param paOrders The file operation orders. 966 * @param phProcess Where to return process handle. 967 * @param pfIsChildExitCode Where to indicate whether the return exit code 968 * is from the child or from our setup efforts. 969 */ 970 static int kRedirectExecProcessWithinOnWorker(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs, 971 char **papszEnvVars, const char *pszCwd, unsigned cOrders, 972 REDIRECTORDERS *paOrders, KBOOL *pfIsChildExitCode) 973 { 974 BOOL afReplace[3] = { FALSE, FALSE, FALSE }; 975 HANDLE ahChild[3] = { NULL, NULL, NULL }; 976 int rc = kRedirectOrderToWindowsHandles(pCtx, cOrders, paOrders, afReplace, ahChild); 977 if (rc == 0) 978 { 979 rc = MkWinChildBuiltInExecChild(pCtx->pvWorker, pszExecutable, papszArgs, TRUE /*fQuotedArgv*/, 980 papszEnvVars, pszCwd, afReplace, ahChild); 981 *pfIsChildExitCode = K_TRUE; 982 } 983 return rc; 984 } 985 # endif /* !KMK_BUILTIN_STANDALONE */ 850 986 851 987 #endif /* KBUILD_OS_WINDOWS */ … … 964 1100 # ifdef KBUILD_OS_WINDOWS 965 1101 /* Windows is slightly complicated due to handles and winchildren.c. */ 966 HANDLE hProcess = INVALID_HANDLE_VALUE; 967 rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars, 968 pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess); 969 if (rcExit == 0) 970 { 971 # ifndef CONFIG_NEW_WIN_CHILDREN 972 if (process_kmk_register_redirect(hProcess, pPidSpawned) == 0) 973 # else 974 if ( pPidSpawned 975 && MkWinChildCreateRedirect((intptr_t)hProcess, pPidSpawned) == 0) 1102 if (pPidSpawned) 1103 *pPidSpawned = 0; 1104 # ifdef CONFIG_NEW_WIN_CHILDREN 1105 if (pCtx->pvWorker && !pPidSpawned) 1106 rcExit = kRedirectExecProcessWithinOnWorker(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars, 1107 pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, 1108 pfIsChildExitCode); 1109 else 976 1110 # endif 977 { 978 if (cVerbosity > 0) 979 warnx(pCtx, "debug: spawned %d", *pPidSpawned); 980 } 981 else 982 { 983 DWORD dwTmp; 984 # ifndef CONFIG_NEW_WIN_CHILDREN 985 warn(pCtx, "sub_proc is out of slots, waiting for child..."); 986 # else 987 if (pPidSpawned) 988 warn(pCtx, "MkWinChildCreateRedirect failed..."); 989 # endif 990 dwTmp = WaitForSingleObject(hProcess, INFINITE); 991 if (dwTmp != WAIT_OBJECT_0) 992 warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp); 993 994 if (GetExitCodeProcess(hProcess, &dwTmp)) 995 rcExit = (int)dwTmp; 996 else 997 { 998 warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError()); 999 TerminateProcess(hProcess, 127); 1000 rcExit = 127; 1001 } 1002 1003 CloseHandle(hProcess); 1004 if (pPidSpawned) 1005 *pPidSpawned = 0; 1006 *pfIsChildExitCode = K_TRUE; 1007 } 1111 { 1112 HANDLE hProcess = INVALID_HANDLE_VALUE; 1113 rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars, 1114 pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess); 1115 if (rcExit == 0) 1116 rcExit = kRedirectPostnatalCareOnWindows(pCtx, hProcess, cVerbosity, pPidSpawned, pfIsChildExitCode); 1008 1117 } 1009 1118 … … 1052 1161 dwWait = 11; 1053 1162 if (GetExitCodeProcess(hProcess, &dwWait)) 1163 { 1164 *pfIsChildExitCode = K_TRUE; 1054 1165 rcExit = dwWait; 1166 } 1055 1167 else 1056 1168 rcExit = errx(pCtx, 11, "GetExitCodeProcess(%s) failed: %u", pszExecutable, GetLastError());
Note:
See TracChangeset
for help on using the changeset viewer.