Changeset 3158 in kBuild
- Timestamp:
- Mar 18, 2018 9:25:06 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/w32/winchildren.c
r3156 r3158 120 120 /** The make shell to use (copy). */ 121 121 char *pszShell; 122 /** Handle to use for standard out. */ 123 HANDLE hStdOut; 124 /** Handle to use for standard out. */ 125 HANDLE hStdErr; 126 /** Whether to close hStdOut after creating the process. */ 127 BOOL fCloseStdOut; 128 /** Whether to close hStdErr after creating the process. */ 129 BOOL fCloseStdErr; 130 122 131 /** Child process handle. */ 123 132 HANDLE hProcess; … … 313 322 } 314 323 315 316 /**317 * Emulate execv() for restarting kmk after one ore more makefiles has been318 * made.319 *320 * Does not return.321 *322 * @param papszArgs The arguments.323 * @param papszEnv The environment.324 */325 void MkWinChildReExecMake(char **papszArgs, char **papszEnv)326 {327 fatal(NILF, 0, __FUNCTION__ "not implemented!\n");328 }329 330 324 /** 331 325 * Used by mkWinChildcareWorkerThread() and MkWinChildWait() to get the head … … 1036 1030 { 1037 1031 cwcDst = cbEnvStrings + 32; 1038 pwszzDst = (WCHAR *)xmalloc(cwcDst );1032 pwszzDst = (WCHAR *)xmalloc(cwcDst * sizeof(WCHAR)); 1039 1033 cwcRc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, papszEnv[0], cbEnvStrings, pwszzDst, cwcDst); 1040 1034 if (cwcRc != 0) … … 1217 1211 StartupInfo.cb = sizeof(StartupInfo); 1218 1212 GetStartupInfoW(&StartupInfo); 1213 if ( pChild->u.Process.hStdErr == INVALID_HANDLE_VALUE 1214 && pChild->u.Process.hStdOut == INVALID_HANDLE_VALUE) 1215 StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES; 1216 else 1217 { 1218 StartupInfo.dwFlags |= STARTF_USESTDHANDLES; 1219 StartupInfo.hStdOutput = pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE 1220 ? pChild->u.Process.hStdOut : GetStdHandle(STD_OUTPUT_HANDLE); 1221 StartupInfo.hStdError = pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE 1222 ? pChild->u.Process.hStdErr : GetStdHandle(STD_ERROR_HANDLE); 1223 StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 1224 } 1219 1225 1220 1226 /* … … 1241 1247 fRet = CreateProcessW(pwszImageName, pwszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/, 1242 1248 TRUE /*fInheritHandles*/, fFlags, pwszzEnvironment, NULL /*pwsz*/, &StartupInfo, &ProcInfo); 1249 rc = GetLastError(); 1243 1250 if (fRet) 1244 1251 { … … 1271 1278 (void)fRet; 1272 1279 } 1280 1281 /* 1282 * Close unncessary handles. 1283 */ 1273 1284 CloseHandle(ProcInfo.hThread); 1274 1285 pChild->u.Process.hProcess = ProcInfo.hProcess; 1286 1287 if ( pChild->u.Process.fCloseStdOut 1288 && pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE) 1289 { 1290 CloseHandle(pChild->u.Process.hStdOut); 1291 pChild->u.Process.hStdOut = INVALID_HANDLE_VALUE; 1292 pChild->u.Process.fCloseStdOut = FALSE; 1293 } 1294 if ( pChild->u.Process.fCloseStdErr 1295 && pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE) 1296 { 1297 CloseHandle(pChild->u.Process.hStdErr); 1298 pChild->u.Process.hStdErr = INVALID_HANDLE_VALUE; 1299 pChild->u.Process.fCloseStdErr = FALSE; 1300 } 1275 1301 1276 1302 /* … … 1279 1305 mkWinChildcareWorkerWaitForProcess(pWorker, pChild, ProcInfo.hProcess); 1280 1306 } 1307 else 1308 pChild->iExitCode = rc; 1281 1309 } 1282 1310 else … … 1593 1621 pChild->u.Process.hProcess = NULL; 1594 1622 } 1623 if ( pChild->u.Process.fCloseStdOut 1624 && pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE) 1625 { 1626 CloseHandle(pChild->u.Process.hStdOut); 1627 pChild->u.Process.hStdOut = INVALID_HANDLE_VALUE; 1628 pChild->u.Process.fCloseStdOut = FALSE; 1629 } 1630 if ( pChild->u.Process.fCloseStdErr 1631 && pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE) 1632 { 1633 CloseHandle(pChild->u.Process.hStdErr); 1634 pChild->u.Process.hStdErr = INVALID_HANDLE_VALUE; 1635 pChild->u.Process.fCloseStdErr = FALSE; 1636 } 1595 1637 break; 1596 1638 } … … 1758 1800 if (pszShell) 1759 1801 pChild->u.Process.pszShell = xstrdup(pszShell); 1802 pChild->u.Process.hStdOut = INVALID_HANDLE_VALUE; 1803 pChild->u.Process.hStdErr = INVALID_HANDLE_VALUE; 1760 1804 1761 1805 return mkWinChildPushToCareWorker(pChild, pPid); 1762 1806 } 1763 1807 1808 /** 1809 * Creates a chile process with a pipe hooked up to stdout. 1810 * 1811 * @returns 0 on success, non-zero on failure. 1812 * @param papszArgs The argument vector. 1813 * @param papszEnv The environment vector (optional). 1814 * @param fdErr File descriptor to hook up to stderr. 1815 * @param pPid Where to return the pid. 1816 * @param pfdReadPipe Where to return the read end of the pipe. 1817 */ 1764 1818 int MkWinChildCreateWithStdOutPipe(char **papszArgs, char **papszEnv, int fdErr, pid_t *pPid, int *pfdReadPipe) 1765 1819 { 1766 fatal(NILF, 0, __FUNCTION__ "not implemented!\n"); 1820 /* 1821 * Create the pipe. 1822 */ 1823 HANDLE hReadPipe; 1824 HANDLE hWritePipe; 1825 if (CreatePipe(&hReadPipe, &hWritePipe, NULL, 0 /* default size */)) 1826 { 1827 if (SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT /* clear */ , HANDLE_FLAG_INHERIT /*set*/)) 1828 { 1829 int fdReadPipe = _open_osfhandle((intptr_t)hReadPipe, O_RDONLY); 1830 if (fdReadPipe >= 0) 1831 { 1832 PWINCHILD pChild; 1833 int rc; 1834 1835 /* 1836 * Get a handle for fdErr. Ignore failure. 1837 */ 1838 HANDLE hStdErr = INVALID_HANDLE_VALUE; 1839 if (fdErr >= 0) 1840 { 1841 HANDLE hNative = (HANDLE)_get_osfhandle(fdErr); 1842 if (!DuplicateHandle(GetCurrentProcess(), hNative, GetCurrentProcess(), 1843 &hStdErr, 0 /*DesiredAccess*/, TRUE /*fInherit*/, DUPLICATE_SAME_ACCESS)) 1844 { 1845 ONN(error, NILF, _("DuplicateHandle failed on stderr descriptor (%u): %u\n"), fdErr, GetLastError()); 1846 hStdErr = INVALID_HANDLE_VALUE; 1847 } 1848 } 1849 1850 /* 1851 * Push it off to the worker thread. 1852 */ 1853 pChild = mkWinChildNew(WINCHILDTYPE_PROCESS); 1854 pChild->u.Process.papszArgs = mkWinChildCopyStringArray(papszArgs, &pChild->u.Process.cbArgsStrings); 1855 pChild->u.Process.papszEnv = mkWinChildCopyStringArray(papszEnv ? papszEnv : environ, 1856 &pChild->u.Process.cbEnvStrings); 1857 //if (pszShell) 1858 // pChild->u.Process.pszShell = xstrdup(pszShell); 1859 pChild->u.Process.hStdOut = hWritePipe; 1860 pChild->u.Process.hStdErr = hStdErr; 1861 pChild->u.Process.fCloseStdErr = TRUE; 1862 pChild->u.Process.fCloseStdOut = TRUE; 1863 1864 rc = mkWinChildPushToCareWorker(pChild, pPid); 1865 if (rc == 0) 1866 *pfdReadPipe = fdReadPipe; 1867 else 1868 { 1869 ON(error, NILF, _("mkWinChildPushToCareWorker failed on pipe: %d\n"), rc); 1870 close(fdReadPipe); 1871 *pfdReadPipe = -1; 1872 *pPid = -1; 1873 } 1874 return rc; 1875 } 1876 1877 ON(error, NILF, _("_open_osfhandle failed on pipe: %u\n"), errno); 1878 } 1879 else 1880 ON(error, NILF, _("SetHandleInformation failed on pipe: %u\n"), GetLastError()); 1881 if (hReadPipe != INVALID_HANDLE_VALUE) 1882 CloseHandle(hReadPipe); 1883 CloseHandle(hWritePipe); 1884 } 1885 else 1886 ON(error, NILF, _("CreatePipe failed: %u\n"), GetLastError()); 1887 *pfdReadPipe = -1; 1888 *pPid = -1; 1767 1889 return -1; 1768 1890 } … … 1842 1964 } 1843 1965 1966 /** 1967 * Wait for a child process to complete 1968 * 1969 * @returns 0 on success, windows error code on failure. 1970 * @param fBlock Whether to block. 1971 * @param pPid Where to return the pid if a child process 1972 * completed. This is set to zero if none. 1973 * @param piExitCode Where to return the exit code. 1974 * @param piSignal Where to return the exit signal number. 1975 * @param pfCoreDumped Where to return the core dumped indicator. 1976 * @param ppMkChild Where to return the associated struct child pointer. 1977 */ 1844 1978 int MkWinChildWait(int fBlock, pid_t *pPid, int *piExitCode, int *piSignal, int *pfCoreDumped, struct child **ppMkChild) 1845 1979 { … … 1847 1981 1848 1982 *pPid = 0; 1849 *piExitCode = 0;1983 *piExitCode = -222222; 1850 1984 *pfCoreDumped = 0; 1851 1985 *ppMkChild = NULL; … … 1900 2034 } 1901 2035 2036 2037 /** 2038 * Emulate execv() for restarting kmk after one ore more makefiles has been 2039 * made. 2040 * 2041 * Does not return. 2042 * 2043 * @param papszArgs The arguments. 2044 * @param papszEnv The environment. 2045 */ 2046 void MkWinChildReExecMake(char **papszArgs, char **papszEnv) 2047 { 2048 PROCESS_INFORMATION ProcInfo; 2049 STARTUPINFOW StartupInfo; 2050 WCHAR *pwszCommandLine; 2051 WCHAR *pwszzEnvironment; 2052 WCHAR *pwszPathIgnored; 2053 int rc; 2054 2055 /** @todo this code needs testing... */ 2056 2057 /* 2058 * Get the executable name. 2059 */ 2060 WCHAR wszImageName[MKWINCHILD_MAX_PATH]; 2061 DWORD cwcImageName = GetModuleFileNameW(GetModuleHandle(NULL), wszImageName, MKWINCHILD_MAX_PATH); 2062 if (cwcImageName == 0) 2063 ON(fatal, NILF, _("MkWinChildReExecMake: GetModuleFileName failed: %u\n"), GetLastError()); 2064 2065 /* 2066 * Create the command line and environment. 2067 */ 2068 rc = mkWinChildcareWorkerConvertCommandline(papszArgs, 0 /*fFlags*/, &pwszCommandLine); 2069 if (rc != 0) 2070 ON(fatal, NILF, _("MkWinChildReExecMake: mkWinChildcareWorkerConvertCommandline failed: %u\n"), rc); 2071 2072 rc = mkWinChildcareWorkerConvertEnvironment(papszEnv ? papszEnv : environ, 0 /*cbEnvStrings*/, 2073 &pwszzEnvironment, &pwszPathIgnored); 2074 if (rc != 0) 2075 ON(fatal, NILF, _("MkWinChildReExecMake: mkWinChildcareWorkerConvertEnvironment failed: %u\n"), rc); 2076 2077 2078 /* 2079 * Fill out the startup info and try create the process. 2080 */ 2081 memset(&ProcInfo, 0, sizeof(ProcInfo)); 2082 memset(&StartupInfo, 0, sizeof(StartupInfo)); 2083 StartupInfo.cb = sizeof(StartupInfo); 2084 GetStartupInfoW(&StartupInfo); 2085 if (!CreateProcessW(wszImageName, pwszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/, 2086 TRUE /*fInheritHandles*/, 0 /*fFlags*/, pwszzEnvironment, NULL /*pwsz*/, 2087 &StartupInfo, &ProcInfo)) 2088 ON(fatal, NILF, _("MkWinChildReExecMake: CreateProcessW failed: %u\n"), GetLastError()); 2089 CloseHandle(ProcInfo.hThread); 2090 2091 /* 2092 * Wait for it to complete and forward the status code to our parent. 2093 */ 2094 for (;;) 2095 { 2096 DWORD dwExitCode = -2222; 2097 DWORD dwStatus = WaitForSingleObject(ProcInfo.hProcess, INFINITE); 2098 if ( dwStatus == WAIT_IO_COMPLETION 2099 || dwStatus == WAIT_TIMEOUT /* whatever */) 2100 continue; /* however unlikely, these aren't fatal. */ 2101 2102 /* Get the status code and terminate. */ 2103 if (dwStatus == WAIT_OBJECT_0) 2104 { 2105 if (GetExitCodeProcess(ProcInfo.hProcess, &dwExitCode)) 2106 ON(fatal, NILF, _("MkWinChildReExecMake: GetExitCodeProcess failed: %u\n"), GetLastError()); 2107 else 2108 dwExitCode = -2222; 2109 } 2110 else if (dwStatus) 2111 dwExitCode = dwStatus; 2112 2113 CloseHandle(ProcInfo.hProcess); 2114 for (;;) 2115 exit(dwExitCode); 2116 } 2117 } 2118 2119 1902 2120 int MkWinChildUnrelatedCloseOnExec(int fd) 1903 2121 { … … 1914 2132 } 1915 2133 2134 2135
Note:
See TracChangeset
for help on using the changeset viewer.