- Timestamp:
- Mar 16, 2020 2:31:38 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kBuild/tools/VCC100AMD64.kmk
r3303 r3313 80 80 ifneq ($(substr $(PATH_TOOL_VCC100AMD64_BIN),-9),x86_amd64) 81 81 TOOL_VCC100AMD64_KSUBMIT ?= kmk_builtin_kSubmit --64-bit 82 TOOL_VCC100AMD64_KSUBMIT_DD = $(TOOL_VCC100AMD64_KSUBMIT) -- 82 if $(KBUILD_KMK_REVISION) > 3311 83 TOOL_VCC100AMD64_KSUBMIT_SPECIAL_ENV = -s "_MSPDBSRV_ENDPOINT_=kBuild_vcc10_amd64_@@AUTHENTICATION_ID@@_$(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB),common,@@PROCESS_GROUP@@)" 84 endif 85 TOOL_VCC100AMD64_KSUBMIT_DD = $(TOOL_VCC100AMD64_KSUBMIT) $(TOOL_VCC100AMD64_KSUBMIT_SPECIAL_ENV) -- 83 86 else 84 87 # "fatal error C1902: Program database manager mismatch; please check your installation" when mixing with the 32-bit compiler. … … 162 165 TOOL_VCC100AMD64_COMPILE_C_DONT_PURGE_OUTPUT := 1 # speed 163 166 define TOOL_VCC100AMD64_COMPILE_C_CMDS 164 $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT) -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\ 167 $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT) $(TOOL_VCC100AMD64_KSUBMIT_SPECIAL_ENV) \ 168 -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\ 165 169 -- $(TOOL_VCC100AMD64_CC) -c\ 166 170 $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ … … 202 206 TOOL_VCC100AMD64_COMPILE_CXX_DONT_PURGE_OUTPUT := 1 # speed 203 207 define TOOL_VCC100AMD64_COMPILE_CXX_CMDS 204 $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT) -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\205 - - $(TOOL_VCC100AMD64_CXX) -c\208 $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT) $(TOOL_VCC100AMD64_KSUBMIT_SPECIAL_ENV) \ 209 -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj) -- $(TOOL_VCC100AMD64_CXX) -c\ 206 210 $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ 207 211 $(if-expr defined($(target)_PCH_HDR)\ … … 246 250 define TOOL_VCC100AMD64-PCH_COMPILE_CXX_CMDS 247 251 $(QUIET)$(RM) -f -- $($(target)_1_VCC_PCH_FILE) $($(target)_1_VCC_COMMON_OBJ_PDB) 248 $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT) --no-pch-caching -P $(DEP_OBJ_INT) -f -s -q -e .pch -o $(dep) -t $(obj) $(obj)\ 252 $(QUIET)$(TOOL_VCC100AMD64_KSUBMIT) --no-pch-caching $(TOOL_VCC100AMD64_KSUBMIT_SPECIAL_ENV) \ 253 -P $(DEP_OBJ_INT) -f -s -q -e .pch -o $(dep) -t $(obj) $(obj)\ 249 254 -- $(TOOL_VCC100AMD64_CXX) -c -Yc\ 250 255 $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ -
trunk/kBuild/tools/VCC100X86.kmk
r3303 r3313 78 78 ifeq ($(KBUILD_HOST),win) 79 79 TOOL_VCC100X86_KSUBMIT ?= kmk_builtin_kSubmit --32-bit 80 TOOL_VCC100X86_KSUBMIT_DD = $(TOOL_VCC100X86_KSUBMIT) -- 80 if $(KBUILD_KMK_REVISION) > 3311 81 TOOL_VCC100X86_KSUBMIT_SPECIAL_ENV = -s "_MSPDBSRV_ENDPOINT_=kBuild_vcc10_x86_@@AUTHENTICATION_ID@@_$(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB),common,@@PROCESS_GROUP@@)" 82 endif 83 TOOL_VCC100X86_KSUBMIT_DD = $(TOOL_VCC100X86_KSUBMIT) $(TOOL_VCC100X86_KSUBMIT_SPECIAL_ENV) -- 81 84 endif 82 85 endif … … 155 158 TOOL_VCC100X86_COMPILE_C_DONT_PURGE_OUTPUT = 1 # speed 156 159 define TOOL_VCC100X86_COMPILE_C_CMDS 157 $(QUIET)$(TOOL_VCC100X86_KSUBMIT) -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\ 160 $(QUIET)$(TOOL_VCC100X86_KSUBMIT) $(TOOL_VCC100X86_KSUBMIT_SPECIAL_ENV) \ 161 -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\ 158 162 -- $(TOOL_VCC100X86_CC) -c\ 159 163 $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ … … 195 199 TOOL_VCC100X86_COMPILE_CXX_DONT_PURGE_OUTPUT = 1 # speed 196 200 define TOOL_VCC100X86_COMPILE_CXX_CMDS 197 $(QUIET)$(TOOL_VCC100X86_KSUBMIT) -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\ 201 $(QUIET)$(TOOL_VCC100X86_KSUBMIT) $(TOOL_VCC100X86_KSUBMIT_SPECIAL_ENV) \ 202 -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\ 198 203 -- $(TOOL_VCC100X86_CXX) -c\ 199 204 $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ … … 238 243 ifdef TOOL_VCC100X86_KSUBMIT 239 244 define TOOL_VCC100X86-PCH_COMPILE_CXX_CMDS 240 $(QUIET)$(TOOL_VCC100X86_KSUBMIT) --no-pch-caching -P $(DEP_OBJ_INT) -f -s -q -e .pch -o $(dep) -t $(obj) $(obj)\ 245 $(RM) -f -- "$($(target)_1_VCC_COMMON_OBJ_PDB)" 246 $(QUIET)$(TOOL_VCC100X86_KSUBMIT) --no-pch-caching $(TOOL_VCC100X86_KSUBMIT_SPECIAL_ENV) \ 247 -P $(DEP_OBJ_INT) -f -s -q -e .pch -o $(dep) -t $(obj) $(obj)\ 241 248 -- $(TOOL_VCC100X86_CXX) -c -Yc\ 242 249 $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ … … 257 264 $(subst /,\\,$(abspath $(source))) 258 265 $(QUIET)$(DEP_OBJ) -f -s -q -e .pch -o $(dep) -t $(obj) $(obj) 259 260 266 endef 261 267 endif # !TOOL_VCC100X86_KSUBMIT -
trunk/src/kWorker/kWorker.c
r3200 r3313 195 195 196 196 197 /** 198 * Generate CRT slot wrapper functions. 199 */ 200 #define CRT_SLOT_FUNCTION_WRAPPER(a_RetTypeAndCallConv, a_FnName, a_aArgsDecl, a_aArgCall) \ 201 static a_RetTypeAndCallConv a_FnName##00 a_aArgsDecl { const unsigned iCrtSlot = 0; return a_FnName##_wrapped a_aArgCall; } \ 202 static a_RetTypeAndCallConv a_FnName##01 a_aArgsDecl { const unsigned iCrtSlot = 1; return a_FnName##_wrapped a_aArgCall; } \ 203 static a_RetTypeAndCallConv a_FnName##02 a_aArgsDecl { const unsigned iCrtSlot = 2; return a_FnName##_wrapped a_aArgCall; } \ 204 static a_RetTypeAndCallConv a_FnName##03 a_aArgsDecl { const unsigned iCrtSlot = 3; return a_FnName##_wrapped a_aArgCall; } \ 205 static a_RetTypeAndCallConv a_FnName##04 a_aArgsDecl { const unsigned iCrtSlot = 4; return a_FnName##_wrapped a_aArgCall; } \ 206 static a_RetTypeAndCallConv a_FnName##05 a_aArgsDecl { const unsigned iCrtSlot = 5; return a_FnName##_wrapped a_aArgCall; } \ 207 static a_RetTypeAndCallConv a_FnName##06 a_aArgsDecl { const unsigned iCrtSlot = 6; return a_FnName##_wrapped a_aArgCall; } \ 208 static a_RetTypeAndCallConv a_FnName##07 a_aArgsDecl { const unsigned iCrtSlot = 7; return a_FnName##_wrapped a_aArgCall; } \ 209 static a_RetTypeAndCallConv a_FnName##08 a_aArgsDecl { const unsigned iCrtSlot = 8; return a_FnName##_wrapped a_aArgCall; } \ 210 static a_RetTypeAndCallConv a_FnName##09 a_aArgsDecl { const unsigned iCrtSlot = 9; return a_FnName##_wrapped a_aArgCall; } \ 211 static a_RetTypeAndCallConv a_FnName##10 a_aArgsDecl { const unsigned iCrtSlot = 10; return a_FnName##_wrapped a_aArgCall; } \ 212 static a_RetTypeAndCallConv a_FnName##11 a_aArgsDecl { const unsigned iCrtSlot = 11; return a_FnName##_wrapped a_aArgCall; } \ 213 static a_RetTypeAndCallConv a_FnName##12 a_aArgsDecl { const unsigned iCrtSlot = 12; return a_FnName##_wrapped a_aArgCall; } \ 214 static a_RetTypeAndCallConv a_FnName##13 a_aArgsDecl { const unsigned iCrtSlot = 13; return a_FnName##_wrapped a_aArgCall; } \ 215 static a_RetTypeAndCallConv a_FnName##14 a_aArgsDecl { const unsigned iCrtSlot = 14; return a_FnName##_wrapped a_aArgCall; } \ 216 static a_RetTypeAndCallConv a_FnName##15 a_aArgsDecl { const unsigned iCrtSlot = 15; return a_FnName##_wrapped a_aArgCall; } \ 217 static a_RetTypeAndCallConv a_FnName##16 a_aArgsDecl { const unsigned iCrtSlot = 16; return a_FnName##_wrapped a_aArgCall; } \ 218 static a_RetTypeAndCallConv a_FnName##17 a_aArgsDecl { const unsigned iCrtSlot = 17; return a_FnName##_wrapped a_aArgCall; } \ 219 static a_RetTypeAndCallConv a_FnName##18 a_aArgsDecl { const unsigned iCrtSlot = 18; return a_FnName##_wrapped a_aArgCall; } \ 220 static a_RetTypeAndCallConv a_FnName##19 a_aArgsDecl { const unsigned iCrtSlot = 19; return a_FnName##_wrapped a_aArgCall; } \ 221 static a_RetTypeAndCallConv a_FnName##20 a_aArgsDecl { const unsigned iCrtSlot = 20; return a_FnName##_wrapped a_aArgCall; } \ 222 static a_RetTypeAndCallConv a_FnName##21 a_aArgsDecl { const unsigned iCrtSlot = 21; return a_FnName##_wrapped a_aArgCall; } \ 223 static a_RetTypeAndCallConv a_FnName##22 a_aArgsDecl { const unsigned iCrtSlot = 22; return a_FnName##_wrapped a_aArgCall; } \ 224 static a_RetTypeAndCallConv a_FnName##23 a_aArgsDecl { const unsigned iCrtSlot = 23; return a_FnName##_wrapped a_aArgCall; } \ 225 static a_RetTypeAndCallConv a_FnName##24 a_aArgsDecl { const unsigned iCrtSlot = 24; return a_FnName##_wrapped a_aArgCall; } \ 226 static a_RetTypeAndCallConv a_FnName##25 a_aArgsDecl { const unsigned iCrtSlot = 25; return a_FnName##_wrapped a_aArgCall; } \ 227 static a_RetTypeAndCallConv a_FnName##26 a_aArgsDecl { const unsigned iCrtSlot = 26; return a_FnName##_wrapped a_aArgCall; } \ 228 static a_RetTypeAndCallConv a_FnName##27 a_aArgsDecl { const unsigned iCrtSlot = 27; return a_FnName##_wrapped a_aArgCall; } \ 229 static a_RetTypeAndCallConv a_FnName##28 a_aArgsDecl { const unsigned iCrtSlot = 28; return a_FnName##_wrapped a_aArgCall; } \ 230 static a_RetTypeAndCallConv a_FnName##29 a_aArgsDecl { const unsigned iCrtSlot = 29; return a_FnName##_wrapped a_aArgCall; } \ 231 static a_RetTypeAndCallConv a_FnName##30 a_aArgsDecl { const unsigned iCrtSlot = 30; return a_FnName##_wrapped a_aArgCall; } \ 232 static a_RetTypeAndCallConv a_FnName##31 a_aArgsDecl { const unsigned iCrtSlot = 31; return a_FnName##_wrapped a_aArgCall; } \ 233 static const KUPTR a_FnName[] = \ 234 { \ 235 (KUPTR)a_FnName##00, \ 236 (KUPTR)a_FnName##01, \ 237 (KUPTR)a_FnName##02, \ 238 (KUPTR)a_FnName##03, \ 239 (KUPTR)a_FnName##04, \ 240 (KUPTR)a_FnName##05, \ 241 (KUPTR)a_FnName##06, \ 242 (KUPTR)a_FnName##07, \ 243 (KUPTR)a_FnName##08, \ 244 (KUPTR)a_FnName##09, \ 245 (KUPTR)a_FnName##10, \ 246 (KUPTR)a_FnName##11, \ 247 (KUPTR)a_FnName##12, \ 248 (KUPTR)a_FnName##13, \ 249 (KUPTR)a_FnName##14, \ 250 (KUPTR)a_FnName##15, \ 251 (KUPTR)a_FnName##16, \ 252 (KUPTR)a_FnName##17, \ 253 (KUPTR)a_FnName##18, \ 254 (KUPTR)a_FnName##19, \ 255 (KUPTR)a_FnName##20, \ 256 (KUPTR)a_FnName##21, \ 257 (KUPTR)a_FnName##22, \ 258 (KUPTR)a_FnName##23, \ 259 (KUPTR)a_FnName##24, \ 260 (KUPTR)a_FnName##25, \ 261 (KUPTR)a_FnName##26, \ 262 (KUPTR)a_FnName##27, \ 263 (KUPTR)a_FnName##28, \ 264 (KUPTR)a_FnName##29, \ 265 (KUPTR)a_FnName##30, \ 266 (KUPTR)a_FnName##31, \ 267 } 268 269 197 270 /********************************************************************************************************************************* 198 271 * Structures and Typedefs * … … 221 294 typedef struct KWMODULE 222 295 { 223 /** Pointer to the next image. */ 224 PKWMODULE pNext; 296 /** Pointer to the next image withe the same hash. */ 297 PKWMODULE pNextHash; 298 /** Pointer to the next image in the global list. */ 299 PKWMODULE pNextList; 225 300 /** The normalized path to the image. */ 226 301 const char *pszPath; … … 243 318 /** The of the loaded image bits. */ 244 319 KSIZE cbImage; 320 /** The CRT slot for this module, if applicable (KU8_MAX when not). */ 321 KU8 iCrtSlot; 322 /** Loop prevention when working the tree. */ 323 KBOOL fVisited; 324 /** HACK: Set if re-init is needed (fReInitOnMsPdbSrvEndpointChange). */ 325 KBOOL fNeedReInit; 326 /** HACK: Reinit when _MSPDBSRV_ENDPOINT_ changes, K_FALSE if not applicable. 327 * 1 if applicable but not yet used, 2 if used and have pszMsPdbSrvEndpoint. */ 328 KU8 fReInitOnMsPdbSrvEndpointChange; 329 /** HACK: The old _MSPDBSRV_ENDPOINT_ value. */ 330 char *pszMsPdbSrvEndpoint; 245 331 246 332 union … … 851 937 } KWSANDBOX; 852 938 939 940 /** A CRT slot. */ 941 typedef struct KWCRTSLOT 942 { 943 KU32 iSlot; 944 945 /** The CRT module data. */ 946 PKWMODULE pModule; 947 /** Pointer to the malloc function. */ 948 void * (__cdecl *pfnMalloc)(size_t); 949 950 } KWCRTSLOT; 951 typedef KWCRTSLOT *PKWCRTSLOT; 952 953 853 954 /** Replacement function entry. */ 854 955 typedef struct KWREPLACEMENTFUNCTION … … 860 961 /** The module name (optional). */ 861 962 const char *pszModule; 862 /** The replacement function or data address. */963 /** The replacement function, data address or CRT slot function array. */ 863 964 KUPTR pfnReplacement; 864 965 /** Only replace in the executable. 865 966 * @todo fix the reinitialization of non-native DLLs! */ 866 967 KBOOL fOnlyExe; 968 /** Set if pfnReplacement points to a CRT slot function array. */ 969 KBOOL fCrtSlotArray; 867 970 } KWREPLACEMENTFUNCTION; 868 971 typedef KWREPLACEMENTFUNCTION const *PCKWREPLACEMENTFUNCTION; … … 884 987 #endif 885 988 989 /** 990 * One test job (--full-test). 991 */ 992 typedef struct KWONETEST 993 { 994 /** Where this job originated. */ 995 const char *pszJobSrc; 996 /** The argument number it started with. */ 997 unsigned iJobSrc; 998 /** Set if virgin, clear if modified. */ 999 KBOOL fVirgin; 1000 1001 /** Number of runs to give it. */ 1002 unsigned cRuns; 1003 1004 /** @name kSubmitHandleJobUnpacked arguments 1005 * @{ */ 1006 const char *pszExecutable; 1007 const char *pszCwd; 1008 KU32 cArgs; 1009 const char **papszArgs; 1010 KU32 cEnvVars; 1011 const char **papszEnvVars; 1012 const char *pszSpecialEnv; 1013 KBOOL fWatcomBrainDamange; 1014 KBOOL fNoPchCaching; 1015 KU32 cPostCmdArgs; 1016 const char **papszPostCmdArgs; 1017 /** @} */ 1018 1019 /** Pointer to the next one. */ 1020 struct KWONETEST *pNext; 1021 } KWONETEST; 1022 /** Pointer to one test job. */ 1023 typedef KWONETEST *PKWONETEST; 1024 886 1025 887 1026 /********************************************************************************************************************************* … … 897 1036 static PKWMODULE g_pModPrevInLdBuf = NULL; 898 1037 1038 /** Module list head. */ 1039 static PKWMODULE g_pModuleHead = NULL; 1040 /** Where to insert the next module. */ 1041 static PKWMODULE *g_ppModuleNext = &g_pModuleHead; 1042 899 1043 /** Module hash table. */ 900 1044 static PKWMODULE g_apModules[127]; … … 911 1055 static PKWMODULE g_pModPendingTlsAlloc = NULL; 912 1056 1057 /** CRT slots. 1058 * @note The number of entires here must match CRT_SLOT_FUNCTION_WRAPPER. */ 1059 static KWCRTSLOT g_aCrtSlots[32]; 913 1060 914 1061 /** The file system cache. */ … … 926 1073 /** Whether we should restart the worker. */ 927 1074 static KBOOL g_fRestart = K_FALSE; 1075 1076 /** The process group this worker is tied to (--group option), -1 if none. */ 1077 static KI32 g_iProcessGroup = -1; 928 1078 929 1079 /** Whether control-C/SIGINT or Control-Break/SIGBREAK have been seen. */ … … 1046 1196 static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, 1047 1197 const char *pszSearchPath, PKWMODULE *ppMod); 1198 static PKWMODULE kwLdrModuleForLoadedNative(const char *pszName, KBOOL fEnsureCrtSlot); 1199 static char *kwSandboxDoGetEnvA(PKWSANDBOX pSandbox, const char *pchVar, KSIZE cchVar); 1048 1200 static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle, HANDLE hHandle); 1049 1201 #ifdef WITH_CONSOLE_OUTPUT_BUFFERING … … 1160 1312 fprintf(stderr, "kWorker: error: "); 1161 1313 vfprintf(stderr, pszFormat, va); 1314 fflush(stderr); /* In case it's a pipe. */ 1162 1315 1163 1316 SetLastError(dwSavedErr); … … 1624 1777 if (--pMod->cRefs == 0) 1625 1778 { 1626 /* Unlink it . */1779 /* Unlink it from the hash table. */ 1627 1780 if (!pMod->fExe) 1628 1781 { … … 1630 1783 unsigned idx = pMod->uHashPath % K_ELEMENTS(g_apModules); 1631 1784 if (g_apModules[idx] == pMod) 1632 g_apModules[idx] = pMod->pNext ;1785 g_apModules[idx] = pMod->pNextHash; 1633 1786 else 1634 1787 { 1635 1788 PKWMODULE pPrev = g_apModules[idx]; 1636 1789 kHlpAssert(pPrev != NULL); 1637 while (pPrev->pNext != pMod)1790 while (pPrev->pNextHash != pMod) 1638 1791 { 1639 pPrev = pPrev->pNext ;1792 pPrev = pPrev->pNextHash; 1640 1793 kHlpAssert(pPrev != NULL); 1641 1794 } 1642 pPrev->pNext = pMod->pNext; 1643 } 1795 pPrev->pNextHash = pMod->pNextHash; 1796 } 1797 } 1798 1799 /* Unlink it from the list. */ 1800 if (pMod != g_pModuleHead) 1801 { 1802 PKWMODULE pPrev = g_pModuleHead; 1803 while (pPrev) 1804 { 1805 if (pPrev->pNextList == pMod) 1806 { 1807 pPrev->pNextList = pMod->pNextList; 1808 if (!pMod->pNextList) 1809 g_ppModuleNext = &pPrev->pNextList; 1810 break; 1811 } 1812 pPrev = pPrev->pNextList; 1813 } 1814 kHlpAssert(pPrev != NULL); 1815 } 1816 else 1817 { 1818 g_pModuleHead = pMod->pNextList; 1819 if (!pMod->pNextList) 1820 g_ppModuleNext = &g_pModuleHead; 1644 1821 } 1645 1822 … … 1666 1843 } 1667 1844 1845 if (pMod->iCrtSlot != KU8_MAX) 1846 g_aCrtSlots[pMod->iCrtSlot].pModule = NULL; 1847 1848 if (pMod->pszMsPdbSrvEndpoint) 1849 { 1850 kHlpFree(pMod->pszMsPdbSrvEndpoint); 1851 pMod->pszMsPdbSrvEndpoint = NULL; 1852 } 1853 1668 1854 kHlpFree(pMod); 1669 1855 } … … 1681 1867 static PKWMODULE kwLdrModuleLink(PKWMODULE pMod) 1682 1868 { 1683 unsigned idx = pMod->uHashPath % K_ELEMENTS(g_apModules); 1684 pMod->pNext = g_apModules[idx]; 1685 g_apModules[idx] = pMod; 1869 if (!pMod->fExe) 1870 { 1871 unsigned idx = pMod->uHashPath % K_ELEMENTS(g_apModules); 1872 pMod->pNextHash = g_apModules[idx]; 1873 g_apModules[idx] = pMod; 1874 } 1875 1876 pMod->pNextList = NULL; 1877 *g_ppModuleNext = pMod; 1878 g_ppModuleNext = &pMod->pNextList; 1879 1686 1880 return pMod; 1687 1881 } … … 1748 1942 KU32 iThunk; 1749 1943 const char * const pszImport = (const char *)&pbImage[pImpDesc->Name]; 1944 PKWMODULE pImportMod = NULL; 1750 1945 PIMAGE_THUNK_DATA paThunks = (PIMAGE_THUNK_DATA)&pbImage[pImpDesc->FirstThunk]; 1751 1946 PIMAGE_THUNK_DATA paOrgThunks = (PIMAGE_THUNK_DATA)&pbImage[pImpDesc->OriginalFirstThunk]; … … 1818 2013 } 1819 2014 1820 paThunks[iThunk].u1.AddressOfData = g_aSandboxNativeReplacements[i].pfnReplacement; 2015 /* 2016 * Unslotted replacements are simple. 2017 */ 2018 if (!g_aSandboxNativeReplacements[i].fCrtSlotArray) 2019 paThunks[iThunk].u1.AddressOfData = g_aSandboxNativeReplacements[i].pfnReplacement; 2020 else 2021 { 2022 /* 2023 * Must find our module entry for this module, possibly creating one. 2024 */ 2025 if (!pImportMod) 2026 { 2027 pImportMod = kwLdrModuleForLoadedNative(pszImport, K_TRUE /*fEnsureCrtSlot*/); 2028 if (!pImportMod) 2029 { 2030 kwErrPrintf("Failed to get module '%s' when performing replacements on module '%s'!\n", 2031 pszImport, pMod->pszPath); 2032 break; 2033 } 2034 } 2035 paThunks[iThunk].u1.AddressOfData 2036 = ((KUPTR *)g_aSandboxNativeReplacements[i].pfnReplacement)[pImportMod->iCrtSlot]; 2037 } 1821 2038 break; 1822 2039 } … … 1859 2076 * Create the entry. 1860 2077 */ 1861 PKWMODULE pMod 2078 PKWMODULE pMod = (PKWMODULE)kHlpAllocZ(sizeof(*pMod) + cbPath + cbPath * 2 * sizeof(wchar_t)); 1862 2079 if (pMod) 1863 2080 { … … 1873 2090 pMod->hOurMod = (HMODULE)(KUPTR)pLdrMod->aSegments[0].MapAddress; 1874 2091 pMod->cbImage = (KSIZE)kLdrModSize(pLdrMod); 2092 pMod->iCrtSlot = KU8_MAX; 2093 pMod->fNeedReInit = K_FALSE; 2094 pMod->pszMsPdbSrvEndpoint = NULL; 2095 pMod->fReInitOnMsPdbSrvEndpointChange = kHlpStrNICompAscii(&pMod->pszPath[pMod->offFilename], TUPLE("mspdb")) == 0; 1875 2096 1876 2097 if (fDoReplacements) … … 1906 2127 */ 1907 2128 PKLDRMOD pLdrMod; 1908 int rc = kLdrModOpenNative(pszPath, &pLdrMod);2129 int rc = kLdrModOpenNative(pszPath, KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM, &pLdrMod); 1909 2130 if (rc == 0) 1910 2131 { … … 2267 2488 pMod->fNative = K_FALSE; 2268 2489 pMod->pLdrMod = pLdrMod; 2269 pMod->u.Manual.cImpMods = (KU32)cImports; 2490 pMod->iCrtSlot = KU8_MAX; 2491 pMod->fNeedReInit = K_FALSE; 2492 pMod->fReInitOnMsPdbSrvEndpointChange = K_FALSE; 2493 pMod->pszMsPdbSrvEndpoint = NULL; 2494 pMod->u.Manual.cImpMods = (KU32)cImports; 2270 2495 #if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64) 2271 2496 pMod->u.Manual.fRegisteredFunctionTable = K_FALSE; … … 2310 2535 */ 2311 2536 pMod->hOurMod = (HMODULE)pMod->u.Manual.pbLoad; 2312 if (!fExe) 2313 kwLdrModuleLink(pMod); 2537 kwLdrModuleLink(pMod); 2314 2538 KW_LOG(("New module: %p LB %#010x %s (kLdr)\n", 2315 2539 pMod->u.Manual.pbLoad, pMod->cbImage, pMod->pszPath)); … … 2646 2870 && kHlpStrComp(pMod->pszPath, szNormPath) == 0) 2647 2871 return kwLdrModuleRetain(pMod); 2648 pMod = pMod->pNext ;2872 pMod = pMod->pNextHash; 2649 2873 } while (pMod); 2650 2874 } … … 2776 3000 *ppMod = NULL; 2777 3001 return KERR_GENERAL_FAILURE; 3002 } 3003 3004 3005 /** 3006 * Creates a CRT slot for the given module. 3007 * 3008 * @returns 0 on success, non-zero on failure. 3009 * @param pModule The module. 3010 */ 3011 static int kwLdrModuleCreateCrtSlot(PKWMODULE pModule) 3012 { 3013 KSIZE iSlot; 3014 kHlpAssert(pModule->iCrtSlot == KU8_MAX); 3015 for (iSlot = 0; iSlot < K_ELEMENTS(g_aCrtSlots); iSlot++) 3016 if (g_aCrtSlots[iSlot].pModule == NULL) 3017 { 3018 KLDRADDR uAddr; 3019 int rc; 3020 3021 /* Do the linking: */ 3022 g_aCrtSlots[iSlot].pModule = pModule; 3023 g_aCrtSlots[iSlot].iSlot = (KU32)iSlot; 3024 pModule->iCrtSlot = (KU8)iSlot; 3025 3026 /* resolve symbols: */ 3027 rc = kLdrModQuerySymbol(pModule->pLdrMod, NULL /*pvBits*/, KLDRMOD_BASEADDRESS_MAP, KU32_MAX, "malloc", 6, 3028 NULL /*pvszVersion*/, NULL /*pfnGetForwarder*/, NULL /*pvUser*/, &uAddr, NULL); 3029 *(KUPTR *)&g_aCrtSlots[iSlot].pfnMalloc = rc == 0 ? (KUPTR)uAddr : 0; 3030 if (rc != 0) 3031 kwErrPrintf("Failed to resolved 'malloc' in '%s': %d\n", pModule->pszPath, rc); 3032 3033 return 0; 3034 } 3035 kwErrPrintf("Out of CRT slots!\n"); 3036 return KERR_NO_MEMORY; 3037 } 3038 3039 3040 /** 3041 * Locates the module structure for an already loaded native module. 3042 * 3043 * This will create a module structure if needed. 3044 * 3045 * @returns Pointer to the module structure on success, NULL on failure. 3046 * @param pszName The name of the module. 3047 * @param fEnsureCrtSlot Whether to ensure that it has a valid CRT slot. 3048 */ 3049 static PKWMODULE kwLdrModuleForLoadedNative(const char *pszName, KBOOL fEnsureCrtSlot) 3050 { 3051 /* 3052 * Locate the module and get a normalized path for it. 3053 */ 3054 HANDLE hModule = GetModuleHandleA(pszName); 3055 if (hModule) 3056 { 3057 char szModPath[1024]; 3058 if (GetModuleFileNameA(hModule, szModPath, sizeof(szModPath)) > 0) 3059 { 3060 char szNormPath[1024]; 3061 int rc = kwPathNormalize(szModPath, szNormPath, sizeof(szNormPath)); 3062 if (rc == 0) 3063 { 3064 /* 3065 * Hash the path and look it up. 3066 */ 3067 KU32 uHashPath; 3068 KSIZE const cchPath = kwStrHashEx(szNormPath, &uHashPath); 3069 unsigned idxHash = uHashPath % K_ELEMENTS(g_apModules); 3070 PKWMODULE pMod = g_apModules[idxHash]; 3071 if (pMod) 3072 { 3073 do 3074 { 3075 if ( pMod->uHashPath == uHashPath 3076 && kHlpStrComp(pMod->pszPath, szNormPath) == 0) 3077 { 3078 kwLdrModuleRetain(pMod); 3079 break; 3080 } 3081 pMod = pMod->pNextHash; 3082 } while (pMod); 3083 } 3084 3085 /* 3086 * If not in the hash table, so create a module entry. 3087 */ 3088 if (!pMod) 3089 { 3090 PKLDRMOD pLdrMod; 3091 rc = kLdrModOpenNativeByHandle((KUPTR)hModule, KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM, &pLdrMod); 3092 if (rc == 0) 3093 { 3094 pMod = kwLdrModuleCreateForNativekLdrModule(pLdrMod, szNormPath, cchPath + 1, uHashPath, 3095 K_FALSE /*fDoReplacements*/); 3096 if (!pMod) 3097 { 3098 kLdrModClose(pLdrMod); 3099 kwErrPrintf("out of memory\n"); 3100 } 3101 } 3102 else 3103 kwErrPrintf("kLdrModOpenNativeByHandle failed for %p / '%s': %d\n", hModule, pszName, rc); 3104 } 3105 if (pMod) 3106 { 3107 /* 3108 * Create a CRT slot for the module if necessary. 3109 */ 3110 if (!fEnsureCrtSlot || pMod->iCrtSlot != KU8_MAX) 3111 return pMod; 3112 rc = kwLdrModuleCreateCrtSlot(pMod); 3113 if (rc == 0) 3114 return pMod; 3115 kwLdrModuleRelease(pMod); 3116 } 3117 } 3118 else 3119 kwErrPrintf("kwPathNormalize failed for '%s' (%s): %u!\n", szModPath, pszName, GetLastError()); 3120 } 3121 else 3122 kwErrPrintf("GetModuleFileNameA failed for '%s': %u!\n", pszName, GetLastError()); 3123 } 3124 else 3125 kwErrPrintf("Module '%s' was not found by GetModuleHandleA!\n", pszName); 3126 return NULL; 2778 3127 } 2779 3128 … … 2942 3291 pMod->u.Manual.enmState = KWMODSTATE_INIT_FAILED; 2943 3292 } 3293 } 3294 /* 3295 * Special hack to disconnect mspdbXXX.dll from mspdbsrv.exe when 3296 * _MSPDBSRV_ENDPOINT_ changes value. 3297 */ 3298 else if (pMod->fNeedReInit) 3299 { 3300 int rc2; 3301 KWLDR_LOG(("kwLdrModuleInitTree: mspdb re-init hack: %s\n", pMod->pszPath)); 3302 //fprintf(stderr, "%d: kwLdrModuleInitTree: mspdb re-init hack: %s\n", getpid(), kwSandboxDoGetEnvA(&g_Sandbox, TUPLE("_MSPDBSRV_ENDPOINT_"))); fflush(stderr); 3303 rc = kLdrModCallTerm(pMod->pLdrMod, pMod->u.Manual.pbLoad, (KUPTR)pMod->hOurMod); 3304 rc2 = kLdrModCallInit(pMod->pLdrMod, pMod->u.Manual.pbLoad, (KUPTR)pMod->hOurMod); 3305 if (!rc && !rc2) 3306 { /* likely */ } 3307 else 3308 { 3309 kwErrPrintf("Re-init of '%s' failed: rc=%d rc2=%d\n", pMod->pszPath, rc, rc2); 3310 if (rc2 && !rc) 3311 rc = rc2; 3312 } 3313 pMod->fNeedReInit = K_FALSE; 2944 3314 } 2945 3315 return rc; … … 4586 4956 4587 4957 4958 /** CRT - _wdupenv_s() (see _tdupenv_s(). */ 4959 static errno_t __cdecl kwSandbox_msvcrt__wdupenv_s_wrapped(wchar_t **ppwszValue, size_t *pcwcValue, const wchar_t *pwszVarName, 4960 PKWCRTSLOT pSlot) 4961 { 4962 errno_t rc; 4963 wchar_t *pwszValue; 4964 kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread); 4965 4966 if (ppwszValue) 4967 { 4968 pwszValue = kwSandboxDoGetEnvW(&g_Sandbox, pwszVarName, wcslen(pwszVarName)); 4969 if (pwszValue) 4970 { 4971 size_t cwcValue = wcslen(pwszValue); 4972 wchar_t *pwszDst = pSlot->pfnMalloc ? (wchar_t *)pSlot->pfnMalloc((cwcValue + 1) * sizeof(wchar_t)) : NULL; 4973 if (pwszDst) 4974 { 4975 memcpy(pwszDst, pwszValue, cwcValue * sizeof(wchar_t)); 4976 pwszDst[cwcValue] = '\0'; 4977 *ppwszValue = pwszDst; 4978 if (pcwcValue) 4979 *pcwcValue = cwcValue; 4980 rc = 0; 4981 } 4982 else 4983 { 4984 *ppwszValue = NULL; 4985 if (pcwcValue) 4986 *pcwcValue = 0; 4987 rc = ENOMEM; 4988 } 4989 } 4990 else 4991 { 4992 *ppwszValue = NULL; 4993 if (pcwcValue) 4994 *pcwcValue = 0; 4995 rc = 0; 4996 } 4997 KW_LOG(("_wdupenv_s(,,%ls) -> %d '%ls'\n", pwszVarName, rc, *ppwszValue ? *ppwszValue : L"<null>")); 4998 //fprintf(stderr, "%d: _wdupenv_s(,,%ls) -> %d '%ls'\n", getpid(), pwszVarName, rc, *ppwszValue ? *ppwszValue : L"<null>"); fflush(stderr); // HACKING 4999 } 5000 else 5001 { 5002 /* 5003 * Warning! If mspdb100.dll ends up here, it won't reinitialize the event name 5004 * and continue to use the one it constructed when _MSPDBSRV_ENDPOINT_ 5005 * was set to a value. 5006 */ 5007 if (pcwcValue) 5008 *pcwcValue = 0; 5009 rc = EINVAL; 5010 KW_LOG(("_wdupenv_s(,,%ls) -> EINVAL\n", pwszVarName)); 5011 //fprintf(stderr, "%d: _wdupenv_s(,,%ls) -> EINVAL\n", getpid(), pwszVarName); fflush(stderr); // HACKING 5012 } 5013 return rc; 5014 } 5015 CRT_SLOT_FUNCTION_WRAPPER(errno_t __cdecl, kwSandbox_msvcrt__wdupenv_s, 5016 (wchar_t **ppwszValue, size_t *pcwcValue, const wchar_t *pwszVarName), 5017 (ppwszValue, pcwcValue, pwszVarName, &g_aCrtSlots[iCrtSlot])); 5018 5019 4588 5020 4589 5021 /* … … 4665 5097 return pDynLoad->hmod; 4666 5098 } 4667 pMod = pMod->pNext ;5099 pMod = pMod->pNextHash; 4668 5100 } while (pMod); 4669 5101 } … … 4677 5109 { 4678 5110 PKLDRMOD pLdrMod; 4679 int rc = kLdrModOpenNativeByHandle((KUPTR)hmod, &pLdrMod);5111 int rc = kLdrModOpenNativeByHandle((KUPTR)hmod, KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM, &pLdrMod); 4680 5112 if (rc == 0) 4681 5113 { … … 7790 8222 7791 8223 /* 7792 * Flush the two line buffer, the the combined buffer.8224 * Flush the two line buffer, then the combined buffer. 7793 8225 */ 7794 8226 kwSandboxConsoleFinalFlushLineBuf(pSandbox, &pSandbox->StdErr, "StdErr"); … … 9508 9940 { TUPLE("_amsg_exit"), NULL, (KUPTR)kwSandbox_msvcrt__amsg_exit }, 9509 9941 { TUPLE("terminate"), NULL, (KUPTR)kwSandbox_msvcrt_terminate }, 9942 { TUPLE("_wdupenv_s"), NULL, (KUPTR)kwSandbox_msvcrt__wdupenv_s, K_FALSE /*fOnlyExe*/, K_TRUE /*fCrtSlotArray*/ }, 9510 9943 9511 9944 #if 0 /* used by mspdbXXX.dll */ … … 9604 10037 9605 10038 /** 10039 * Resets the KWMODULE::fVisited flag for _all_ known modules. 10040 */ 10041 static void kwSandboxResetModuleVisited(void) 10042 { 10043 PKWMODULE pMod = g_pModuleHead; 10044 while (pMod) 10045 { 10046 pMod->fVisited = K_FALSE; 10047 pMod = pMod->pNextList; 10048 } 10049 } 10050 10051 10052 /** 9606 10053 * Used by kwSandboxExec to reset the state of the module tree. 9607 10054 * … … 9612 10059 static void kwSandboxResetModuleState(PKWMODULE pMod) 9613 10060 { 9614 if ( !pMod->fNative 9615 && pMod->u.Manual.enmState != KWMODSTATE_NEEDS_BITS) 9616 { 9617 KSIZE iImp; 10061 KWLDR_LOG(("kwSandboxResetModuleState: %d %d %s\n", pMod->fNative, pMod->fVisited, pMod->pszPath)); 10062 if (!pMod->fNative) 10063 { 9618 10064 pMod->u.Manual.enmState = KWMODSTATE_NEEDS_BITS; 9619 iImp = pMod->u.Manual.cImpMods; 9620 while (iImp-- > 0) 9621 kwSandboxResetModuleState(pMod->u.Manual.apImpMods[iImp]); 10065 if (!pMod->fVisited) /* Avoid loops. */ 10066 { 10067 KSIZE iImp; 10068 pMod->fVisited = K_TRUE; 10069 iImp = pMod->u.Manual.cImpMods; 10070 while (iImp-- > 0) 10071 kwSandboxResetModuleState(pMod->u.Manual.apImpMods[iImp]); 10072 } 10073 } 10074 /* Hack: Re-init mspdbXXX.dll when we want to use a different mspdbsrv.exe instance. */ 10075 else if (pMod->fReInitOnMsPdbSrvEndpointChange) 10076 { 10077 const char *pszValue = kwSandboxDoGetEnvA(&g_Sandbox, TUPLE("_MSPDBSRV_ENDPOINT_")); 10078 if (pMod->fReInitOnMsPdbSrvEndpointChange == 1) 10079 { 10080 pMod->fReInitOnMsPdbSrvEndpointChange = 2; 10081 pMod->pszMsPdbSrvEndpoint = pszValue ? kHlpStrDup(pszValue) : NULL; 10082 KWLDR_LOG(("Not re-initing '%s': first time used (_MSPDBSRV_ENDPOINT_ is '%s')\n", 10083 pMod->pszPath, pszValue ? pszValue : "<null>")); 10084 } 10085 else if ( (pszValue == NULL && pMod->pszMsPdbSrvEndpoint == NULL) 10086 || (pszValue != NULL && pMod->pszMsPdbSrvEndpoint != NULL && kHlpStrComp(pszValue, pMod->pszMsPdbSrvEndpoint) == 0)) 10087 KWLDR_LOG(("Not re-initing '%s': _MSPDBSRV_ENDPOINT_ unchanged ('%s')\n", 10088 pMod->pszPath, pszValue ? pszValue : "<null>")); 10089 else 10090 { 10091 KWLDR_LOG(("Re-initing '%s': _MSPDBSRV_ENDPOINT_ changed from '%s' to '%s'\n", pMod->pszPath, 10092 pMod->pszMsPdbSrvEndpoint ? pMod->pszMsPdbSrvEndpoint : "<null>", pszValue ? pszValue : "<null>")); 10093 kHlpFree(pMod->pszMsPdbSrvEndpoint); 10094 if (pszValue != NULL) 10095 pMod->pszMsPdbSrvEndpoint = kHlpStrDup(pszValue); 10096 else 10097 pMod->pszMsPdbSrvEndpoint = NULL; 10098 pMod->fNeedReInit = K_TRUE; 10099 } 9622 10100 } 9623 10101 } … … 10207 10685 * Do module initialization. 10208 10686 */ 10687 kwSandboxResetModuleVisited(); 10209 10688 kwSandboxResetModuleState(pTool->u.Sandboxed.pExe); 10210 10689 rc = kwLdrModuleInitTree(pTool->u.Sandboxed.pExe); … … 10292 10771 #endif 10293 10772 kwSandboxCleanup(&g_Sandbox); 10773 /** @todo Flush sandboxed native CRTs too. */ 10294 10774 } 10295 10775 else … … 10323 10803 } 10324 10804 10325 return kwErrPrintfRc(42 + 5 , "Unknown post command: '%s'\n", pszCmd); 10805 return kwErrPrintfRc(42 + 5, "Unknown post command: '%s'\n", pszCmd); 10806 } 10807 10808 10809 /** 10810 * Helper for kSubmitHandleSpecialEnvVar that gets the current process group. 10811 */ 10812 static unsigned kwGetCurrentProcessorGroup(void) 10813 { 10814 typedef BOOL (WINAPI *PFNGETTHREADGROUPAFFINITY)(HANDLE, GROUP_AFFINITY *); 10815 HMODULE hmodKernel32 = GetModuleHandleW(L"KERNEL32.DLL"); 10816 PFNGETTHREADGROUPAFFINITY pfnGetter = (PFNGETTHREADGROUPAFFINITY)GetProcAddress(hmodKernel32, "GetThreadGroupAffinity"); 10817 if (pfnGetter) 10818 { 10819 GROUP_AFFINITY GroupAffinity; 10820 memset(&GroupAffinity, 0, sizeof(GroupAffinity)); 10821 if (pfnGetter(GetCurrentThread(), &GroupAffinity)) 10822 return GroupAffinity.Group; 10823 } 10824 return 0; 10825 } 10826 10827 10828 /** 10829 * Helper for kSubmitHandleSpecialEnvVar that gets the current process group. 10830 */ 10831 static KSIZE kwGetCurrentAuthenticationIdAsString(char *pszValue) 10832 { 10833 KSIZE cchRet = 0; 10834 HANDLE hToken; 10835 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 10836 { 10837 DWORD cbRet; 10838 TOKEN_STATISTICS TokenStats; 10839 memset(&TokenStats, 0, sizeof(TokenStats)); 10840 if (GetTokenInformation(hToken, TokenStatistics, &TokenStats, sizeof(TokenStats), &cbRet)) 10841 cchRet = sprintf(pszValue, "%" KX64_PRI, 10842 ((KU64)TokenStats.AuthenticationId.HighPart << 32) | TokenStats.AuthenticationId.LowPart); 10843 else 10844 kwErrPrintf("GetTokenInformation/TokenStatistics failed: %u\n", GetLastError()); 10845 CloseHandle(hToken); 10846 } 10847 else 10848 kwErrPrintf("OpenProcessToken failed: %u\n", GetLastError()); 10849 return cchRet; 10850 } 10851 10852 10853 /** 10854 * Look for and expand the special environment variable. 10855 * 10856 * We the special variable contains elements like "@@VAR_NAME@@" that kmk 10857 * couldn't accuratly determine. Currently the following variables are 10858 * implemented: 10859 * - "@@PROCESSOR_GROUP@@" - The processor group number. 10860 * - "@@AUTHENTICATION_ID@@" - The authentication ID from the process token. 10861 * - "@@PID@@" - The kWorker process ID. 10862 * - "@@@@" - Escaped "@@". 10863 * - "@@DEBUG_COUNTER@@" - An ever increasing counter (starts at zero). 10864 */ 10865 static int kSubmitHandleSpecialEnvVar(KU32 cEnvVars, const char **papszEnvVars, const char *pszSpecialEnv, char **ppszToFree) 10866 { 10867 KSIZE const cchSpecialEnv = kHlpStrLen(pszSpecialEnv); 10868 KU32 i = cEnvVars; 10869 while (i-- > 0) 10870 if ( kHlpStrNComp(papszEnvVars[i], pszSpecialEnv, cchSpecialEnv) == 0 10871 && papszEnvVars[i][cchSpecialEnv] == '=') 10872 { 10873 /* We will expand stuff like @@NAME@@ */ 10874 const char *pszValue = papszEnvVars[i]; 10875 KSIZE offDst = 0; 10876 char szTmp[1024]; 10877 for (;;) 10878 { 10879 const char *pszAt = kHlpStrChr(pszValue, '@'); 10880 while (pszAt && pszAt[1] != '@') 10881 pszAt = kHlpStrChr(pszAt + 1, '@'); 10882 if (pszAt) 10883 { 10884 KSIZE cchSrc = pszAt - pszValue; 10885 if (offDst + cchSrc < sizeof(szTmp)) 10886 { 10887 char szSrc[64]; 10888 10889 kHlpMemCopy(&szTmp[offDst], pszValue, cchSrc); 10890 offDst += cchSrc; 10891 pszValue = pszAt + 2; 10892 10893 if (kHlpStrNComp(pszValue, "PROCESS_GROUP@@", 15) == 0) 10894 { 10895 pszValue += 15; 10896 if (g_iProcessGroup == -1) 10897 g_iProcessGroup = kwGetCurrentProcessorGroup(); 10898 cchSrc = sprintf(szSrc, "%u", g_iProcessGroup); 10899 } 10900 else if (kHlpStrNComp(pszValue, "AUTHENTICATION_ID@@", 19) == 0) 10901 { 10902 pszValue += 19; 10903 cchSrc = kwGetCurrentAuthenticationIdAsString(szSrc); 10904 } 10905 else if (kHlpStrNComp(pszValue, "PID@@", 5) == 0) 10906 { 10907 pszValue += 5; 10908 cchSrc = sprintf(szSrc, "%d", getpid()); 10909 } 10910 else if (kHlpStrNComp(pszValue, "@@", 2) == 0) 10911 { 10912 pszValue += 2; 10913 szSrc[0] = '@'; 10914 szSrc[1] = '@'; 10915 szSrc[2] = '\0'; 10916 cchSrc = 2; 10917 } 10918 else if (kHlpStrNComp(pszValue, "DEBUG_COUNTER@@", 15) == 0) 10919 { 10920 static unsigned int s_iCounter = 0; 10921 pszValue += 15; 10922 cchSrc = sprintf(szSrc, "%u", s_iCounter++); 10923 } 10924 else 10925 return kwErrPrintfRc(42 + 6, "Special environment variable contains unknown reference: '%s'!\n", 10926 pszValue - 2); 10927 if (offDst + cchSrc < sizeof(szTmp)) 10928 { 10929 kHlpMemCopy(&szTmp[offDst], szSrc, cchSrc); 10930 offDst += cchSrc; 10931 continue; 10932 } 10933 } 10934 } 10935 else 10936 { 10937 KSIZE cchSrc = kHlpStrLen(pszValue); 10938 if (offDst + cchSrc < sizeof(szTmp)) 10939 { 10940 kHlpMemCopy(&szTmp[offDst], pszValue, cchSrc); 10941 offDst += cchSrc; 10942 break; 10943 } 10944 } 10945 return kwErrPrintfRc(42 + 6, "Special environment variable value too long!\n"); 10946 } 10947 szTmp[offDst] = '\0'; 10948 10949 /* Return a copy of it: */ 10950 papszEnvVars[i] = *ppszToFree = kHlpDup(szTmp, offDst + 1); 10951 if (papszEnvVars[i]) 10952 { 10953 SetEnvironmentVariableA(pszSpecialEnv, kHlpStrChr(papszEnvVars[i], '=') + 1); /* hack */ 10954 return 0; 10955 } 10956 return kwErrPrintfRc(42 + 6, "Special environment variable: out of memory\n"); 10957 } 10958 10959 return kwErrPrintfRc(42 + 6, "Special environment variable not found: '%s'\n", pszSpecialEnv); 10326 10960 } 10327 10961 … … 10338 10972 * @param cEnvVars The number of environment variables. 10339 10973 * @param papszEnvVars The environment vector. 10974 * @param pszSpecialEnv Name of special environment variable that 10975 * requires selective expansion here. 10340 10976 * @param fNoPchCaching Whether to disable precompiled header file 10341 10977 * caching. Avoid trouble when creating them. … … 10345 10981 static int kSubmitHandleJobUnpacked(const char *pszExecutable, const char *pszCwd, 10346 10982 KU32 cArgs, const char **papszArgs, KBOOL fWatcomBrainDamange, 10347 KU32 cEnvVars, const char **papszEnvVars, KBOOL fNoPchCaching,10348 K U32 cPostCmdArgs, const char **papszPostCmdArgs)10983 KU32 cEnvVars, const char **papszEnvVars, const char *pszSpecialEnv, 10984 KBOOL fNoPchCaching, KU32 cPostCmdArgs, const char **papszPostCmdArgs) 10349 10985 { 10350 10986 int rcExit; 10351 10987 PKWTOOL pTool; 10988 char *pszSpecialEnvFree = NULL; 10352 10989 10353 10990 KW_LOG(("\n\nkSubmitHandleJobUnpacked: '%s' in '%s' cArgs=%u cEnvVars=%u cPostCmdArgs=%u\n", … … 10363 11000 #endif 10364 11001 g_cJobs++; 11002 11003 /* 11004 * Expand pszSpecialEnv if present. 11005 */ 11006 if (*pszSpecialEnv) 11007 { 11008 rcExit = kSubmitHandleSpecialEnvVar(cEnvVars, papszEnvVars, pszSpecialEnv, &pszSpecialEnvFree); 11009 if (!rcExit) 11010 { /* likely */ } 11011 else 11012 return rcExit; 11013 } 10365 11014 10366 11015 /* … … 10434 11083 else 10435 11084 rcExit = 42 + 1; 11085 if (pszSpecialEnvFree) 11086 { 11087 SetEnvironmentVariableA(pszSpecialEnv, NULL); /* hack */ 11088 kHlpFree(pszSpecialEnvFree); 11089 } 10436 11090 return rcExit; 10437 11091 } … … 10544 11198 cbMsg -= 2; 10545 11199 10546 /* Post command argument count (can be zero). */10547 if (cbMsg >= sizeof(KU32))11200 /* Name of special enviornment variable requiring selective expansion. */ 11201 if (cbMsg >= 1) 10548 11202 { 10549 KU32 cPostCmdArgs; 10550 kHlpMemCopy(&cPostCmdArgs, pszMsg, sizeof(cPostCmdArgs)); 10551 pszMsg += sizeof(cPostCmdArgs); 10552 cbMsg -= sizeof(cPostCmdArgs); 10553 10554 if (cPostCmdArgs >= 0 && cPostCmdArgs < 32) 11203 const char *pszSpecialEnv = pszMsg; 11204 cbTmp = kHlpStrLen(pszMsg); 11205 pszMsg += cbTmp + 1; 11206 cbMsg -= K_MIN(cbMsg, cbTmp + 1); 11207 11208 /* Post command argument count (can be zero). */ 11209 if (cbMsg >= sizeof(KU32)) 10555 11210 { 10556 char const *apszPostCmdArgs[32+1]; 10557 for (i = 0; i < cPostCmdArgs; i++) 11211 KU32 cPostCmdArgs; 11212 kHlpMemCopy(&cPostCmdArgs, pszMsg, sizeof(cPostCmdArgs)); 11213 pszMsg += sizeof(cPostCmdArgs); 11214 cbMsg -= sizeof(cPostCmdArgs); 11215 11216 if (cPostCmdArgs >= 0 && cPostCmdArgs < 32) 10558 11217 { 10559 apszPostCmdArgs[i] = pszMsg; 10560 cbTmp = kHlpStrLen(pszMsg) + 1; 10561 pszMsg += cbTmp; 10562 if ( cbTmp < cbMsg 10563 || (cbTmp == cbMsg && i + 1 == cPostCmdArgs)) 10564 cbMsg -= cbTmp; 11218 char const *apszPostCmdArgs[32+1]; 11219 for (i = 0; i < cPostCmdArgs; i++) 11220 { 11221 apszPostCmdArgs[i] = pszMsg; 11222 cbTmp = kHlpStrLen(pszMsg) + 1; 11223 pszMsg += cbTmp; 11224 if ( cbTmp < cbMsg 11225 || (cbTmp == cbMsg && i + 1 == cPostCmdArgs)) 11226 cbMsg -= cbTmp; 11227 else 11228 { 11229 cbMsg = KSIZE_MAX; 11230 break; 11231 } 11232 } 11233 if (cbMsg == 0) 11234 { 11235 apszPostCmdArgs[cPostCmdArgs] = NULL; 11236 11237 /* 11238 * The next step. 11239 */ 11240 rcExit = kSubmitHandleJobUnpacked(pszExecutable, pszCwd, 11241 cArgs, papszArgs, fWatcomBrainDamange, 11242 cEnvVars, papszEnvVars, pszSpecialEnv, 11243 fNoPchCaching, 11244 cPostCmdArgs, apszPostCmdArgs); 11245 } 11246 else if (cbMsg == KSIZE_MAX) 11247 kwErrPrintf("Detected bogus message unpacking post command and its arguments!\n"); 10565 11248 else 10566 { 10567 cbMsg = KSIZE_MAX; 10568 break; 10569 } 11249 kwErrPrintf("Message has %u bytes unknown trailing bytes\n", cbMsg); 10570 11250 } 10571 if (cbMsg == 0)10572 {10573 apszPostCmdArgs[cPostCmdArgs] = NULL;10574 10575 /*10576 * The next step.10577 */10578 rcExit = kSubmitHandleJobUnpacked(pszExecutable, pszCwd,10579 cArgs, papszArgs, fWatcomBrainDamange,10580 cEnvVars, papszEnvVars, fNoPchCaching,10581 cPostCmdArgs, apszPostCmdArgs);10582 }10583 else if (cbMsg == KSIZE_MAX)10584 kwErrPrintf("Detected bogus message unpacking post command and its arguments!\n");10585 11251 else 10586 kwErrPrintf(" Message has %u bytes unknown trailing bytes\n", cbMsg);11252 kwErrPrintf("Bogus post command argument count: %u %#x\n", cPostCmdArgs, cPostCmdArgs); 10587 11253 } 10588 11254 else 10589 kwErrPrintf(" Bogus post command argument count: %u %#x\n", cPostCmdArgs, cPostCmdArgs);11255 kwErrPrintf("Detected bogus message looking for the post command argument count!\n"); 10590 11256 } 10591 11257 else 10592 kwErrPrintf("Detected bogus message looking for the post command argument count!\n");11258 kwErrPrintf("Detected bogus message unpacking special environment variable!\n"); 10593 11259 } 10594 11260 else 10595 kwErrPrintf("Detected bogus message unpacking environment variables!\n");11261 kwErrPrintf("Detected bogus message unpacking flags!\n"); 10596 11262 kHlpFree((void *)papszEnvVars); 10597 11263 } … … 10889 11555 const char *pszCwd = getcwd(szCwd, sizeof(szCwd)); 10890 11556 KU32 cEnvVars; 11557 char **papszEnvVars; 11558 const char *pszSpecialEnv = ""; 11559 const char *pszSpecialEnvFull = NULL; 10891 11560 KBOOL fWatcomBrainDamange = K_FALSE; 10892 11561 KBOOL fNoPchCaching = K_FALSE; … … 10934 11603 } 10935 11604 11605 /* Optional directory change. */ 11606 if ( i < argc 11607 && ( strcmp(argv[i], "--set-special") == 0 11608 || strcmp(argv[i], "-s") == 0 ) ) 11609 { 11610 i++; 11611 if (i >= argc) 11612 return kwErrPrintfRc(2, "--set-special takes an argument!\n"); 11613 pszSpecialEnvFull = argv[i++]; 11614 putenv(pszSpecialEnvFull); 11615 pszSpecialEnv = strdup(pszSpecialEnvFull); 11616 *strchr(pszSpecialEnv, '=') = '\0'; 11617 } 11618 10936 11619 /* Trigger breakpoint */ 10937 11620 if ( i < argc … … 10958 11641 10959 11642 /* 10960 * D o the job.11643 * Duplicate the environment. 10961 11644 */ 10962 11645 cEnvVars = 0; 10963 11646 while (environ[cEnvVars] != NULL) 10964 11647 cEnvVars++; 10965 11648 papszEnvVars = (char **)kHlpAllocZ(sizeof(papszEnvVars[0]) * (cEnvVars + 2)); 11649 11650 /* 11651 * Do the job. 11652 */ 10966 11653 for (j = 0; j < cRepeats; j++) 10967 11654 { 11655 memcpy(papszEnvVars, environ, sizeof(papszEnvVars[0]) * cEnvVars); 10968 11656 rcExit = kSubmitHandleJobUnpacked(argv[i], pszCwd, 10969 11657 argc - i, &argv[i], fWatcomBrainDamange, 10970 cEnvVars, environ, fNoPchCaching,11658 cEnvVars, papszEnvVars, pszSpecialEnv, fNoPchCaching, 10971 11659 0, NULL); 10972 11660 KW_LOG(("rcExit=%d\n", rcExit)); 10973 11661 kwSandboxCleanupLate(&g_Sandbox); 11662 } 11663 11664 if (getenv("KWORKER_STATS") != NULL) 11665 kwPrintStats(); 11666 11667 # ifdef WITH_LOG_FILE 11668 if (g_hLogFile != INVALID_HANDLE_VALUE && g_hLogFile != NULL) 11669 CloseHandle(g_hLogFile); 11670 # endif 11671 return rcExit; 11672 } 11673 11674 11675 /** 11676 * Reads @a pszFile into memory and chops it up into an argument vector. 11677 * 11678 * @returns Pointer to the argument vector on success, NULL on failure. 11679 * @param pszFile The file to load. 11680 * @param pcArgs Where to return the number of arguments. 11681 * @param ppszFileContent Where to return the allocation. 11682 */ 11683 static char **kwFullTestLoadArgvFile(const char *pszFile, int *pcArgs, char **ppszFileContent) 11684 { 11685 char **papszArgs = NULL; 11686 FILE *pFile = fopen(pszFile, "r"); 11687 if (pFile) 11688 { 11689 long cbFile; 11690 if ( fseek(pFile, 0, SEEK_END) == 0 11691 && (cbFile = ftell(pFile)) >= 0 11692 && fseek(pFile, 0, SEEK_SET) == 0) 11693 { 11694 char *pszFile = kHlpAllocZ(cbFile + 3); 11695 if (pszFile) 11696 { 11697 size_t cbRead = fread(pszFile, 1, cbFile + 1, pFile); 11698 if ( feof(pFile) 11699 && !ferror(pFile)) 11700 { 11701 size_t off = 0; 11702 int cArgs = 0; 11703 int cAllocated = 0; 11704 char ch; 11705 11706 pszFile[cbRead] = '\0'; 11707 pszFile[cbRead + 1] = '\0'; 11708 pszFile[cbRead + 2] = '\0'; 11709 11710 while ((ch = pszFile[off]) != '\0') 11711 { 11712 char *pszArg; 11713 switch (ch) 11714 { 11715 case ' ': 11716 case '\t': 11717 case '\n': 11718 case '\r': 11719 off++; 11720 continue; 11721 11722 case '\\': 11723 if (pszFile[off + 1] == '\n' || pszFile[off + 1] == '\r') 11724 { 11725 off += 2; 11726 continue; 11727 } 11728 /* fall thru */ 11729 default: 11730 pszArg = &pszFile[off]; 11731 do 11732 ch = pszFile[++off]; 11733 while (ch != '\0' && ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r'); 11734 pszFile[off++] = '\0'; 11735 break; 11736 11737 case '\'': 11738 pszArg = &pszFile[++off]; 11739 while ((ch = pszFile[off]) != '\0' && ch != '\'') 11740 off++; 11741 pszFile[off++] = '\0'; 11742 break; 11743 11744 case '\"': /** @todo escape sequences */ 11745 pszArg = &pszFile[++off]; 11746 while ((ch = pszFile[off]) != '\0' && ch != '"') 11747 off++; 11748 pszFile[off++] = '\0'; 11749 break; 11750 } 11751 if (cArgs + 1 >= cAllocated) 11752 { 11753 void *pvNew; 11754 cAllocated = cAllocated ? cAllocated * 2 : 16; 11755 pvNew = kHlpRealloc(papszArgs, cAllocated * sizeof(papszArgs[0])); 11756 if (pvNew) 11757 papszArgs = (char **)pvNew; 11758 else 11759 { 11760 kHlpFree(papszArgs); 11761 papszArgs = NULL; 11762 break; 11763 } 11764 } 11765 papszArgs[cArgs] = pszArg; 11766 papszArgs[++cArgs] = NULL; 11767 } 11768 *pcArgs = cArgs; 11769 } 11770 else 11771 kwErrPrintf("Error reading '%s'!\n", pszFile); 11772 } 11773 else 11774 kwErrPrintf("Error allocating %lu bytes!\n", cbFile + 2); 11775 } 11776 else 11777 kwErrPrintf("Error seeking '%s'!\n", pszFile); 11778 fclose(pFile); 11779 } 11780 else 11781 kwErrPrintf("Error opening '%s'!\n", pszFile); 11782 return papszArgs; 11783 } 11784 11785 /** 11786 * Appends a string to an string vector (arguments or enviornment). 11787 * 11788 * @returns 0 on success, non-zero on failure (exit code). 11789 * @param ppapszVector Pointer to the string pointer array. 11790 * @param pcEntries Pointer to the array size. 11791 * @param pszAppend The string to append. 11792 */ 11793 static int kwFullTestVectorAppend(const char ***ppapszVector, int *pcEntries, char const *pszAppend) 11794 { 11795 unsigned cEntries = *pcEntries; 11796 if (!(cEntries & 15)) 11797 { 11798 void *pvNew = kHlpRealloc((void *)*ppapszVector, sizeof(char *) * (cEntries + 16 + 1)); 11799 if (pvNew) 11800 *ppapszVector = (const char **)pvNew; 11801 else 11802 return kwErrPrintfRc(2, "Out of memory!\n"); 11803 } 11804 (*ppapszVector)[cEntries] = pszAppend; 11805 (*ppapszVector)[++cEntries] = NULL; 11806 *pcEntries = cEntries; 11807 return 0; 11808 } 11809 11810 11811 /** 11812 * Parses arguments for --full-test. 11813 * 11814 * @returns 0 on success, non-zero on failure (exit code). 11815 */ 11816 static int kwFullTestRunParseArgs(PKWONETEST *ppHead, int *piState, int argc, char **argv, 11817 const char *pszDefaultCwd, int cRecursions, const char *pszJobSrc) 11818 { 11819 PKWONETEST pCur = *ppHead; 11820 int i; 11821 for (i = 0; i < argc; i++) 11822 { 11823 int rc = 0; 11824 const char *pszArg = argv[i]; 11825 if (*pszArg == 'k' && kHlpStrComp(pszArg, "kSubmit") == 0) 11826 { 11827 if (*piState != 0) 11828 { 11829 pCur = (PKWONETEST)kHlpAllocZ(sizeof(*pCur)); 11830 if (!pCur) 11831 return kwErrPrintfRc(2, "Out of memory!\n"); 11832 pCur->fVirgin = K_TRUE; 11833 pCur->pszCwd = pszDefaultCwd; 11834 pCur->cRuns = 1; 11835 pCur->pNext = *ppHead; 11836 *ppHead = pCur; 11837 *piState = 0; 11838 } 11839 else if (!pCur->fVirgin) 11840 return kwErrPrintfRc(2, "Unexpected 'kSubmit' as argument #%u\n", i); 11841 pCur->pszJobSrc = pszJobSrc; 11842 pCur->iJobSrc = i; 11843 continue; /* (to stay virgin) */ 11844 } 11845 else if (*pszArg == '-' && *piState == 0) 11846 { 11847 const char *pszValue = NULL; 11848 char ch = *++pszArg; 11849 pszArg++; 11850 if (ch == '-') 11851 { 11852 ch = '\0'; 11853 if (*pszArg == '\0') /* -- */ 11854 *piState = 2; 11855 /* Translate or handle long options: */ 11856 else if (kHlpStrComp(pszArg, "putenv") == 0 || kHlpStrComp(pszArg, "set") == 0) 11857 ch = 'E'; 11858 else if (kHlpStrComp(pszArg, "special-env") == 0) 11859 ch = 's'; 11860 else if (kHlpStrComp(pszArg, "default-env") == 0) 11861 { 11862 unsigned i; 11863 pCur->cEnvVars = 0; 11864 for (i = 0; environ[i] && rc == 0; i++) 11865 rc = kwFullTestVectorAppend(&pCur->papszEnvVars, &pCur->cEnvVars, kHlpStrDup(environ[i])); /* leaks; unchecked */ 11866 } 11867 else if (kHlpStrComp(pszArg, "chdir") == 0) 11868 ch = 'C'; 11869 else if (kHlpStrComp(pszArg, "post-cmd") == 0) 11870 ch = 'P'; 11871 else if (kHlpStrComp(pszArg, "response-file") == 0) 11872 ch = '@'; 11873 else if (kHlpStrComp(pszArg, "runs") == 0) 11874 ch = 'R'; 11875 else if (kHlpStrComp(pszArg, "watcom-brain-damage") == 0) 11876 pCur->fWatcomBrainDamange = K_TRUE; 11877 else if (kHlpStrComp(pszArg, "no-pch-caching") == 0) 11878 pCur->fNoPchCaching = K_TRUE; 11879 else if (kHlpStrComp(pszArg, "executable") == 0) 11880 ch = 'e'; 11881 else if (kHlpStrComp(pszArg, "breakpoint") == 0) 11882 { 11883 __debugbreak(); 11884 continue; /* (to stay virgin) */ 11885 } 11886 else 11887 return kwErrPrintfRc(2, "Unknown option: --%s\n", pszArg); 11888 pszArg = ""; 11889 } 11890 11891 while (ch != '\0' && rc == 0) 11892 { 11893 /* Fetch value if needed: */ 11894 switch (ch) 11895 { 11896 case '@': 11897 case 'e': 11898 case 'E': 11899 case 's': 11900 case 'C': 11901 case 'R': 11902 if (*pszArg == ':' || *pszArg == '=') 11903 pszValue = &pszArg[1]; 11904 else if (*pszArg) 11905 pszValue = pszArg; 11906 else if (i + 1 < argc) 11907 pszValue = argv[++i]; 11908 else 11909 return kwErrPrintfRc(2, "Option -%c takes a value\n", ch); 11910 pszArg = ""; 11911 break; 11912 } 11913 11914 /* Handle the option: */ 11915 switch (ch) 11916 { 11917 case 'E': 11918 rc = kwFullTestVectorAppend(&pCur->papszEnvVars, &pCur->cEnvVars, pszValue); 11919 break; 11920 case 'C': 11921 pCur->pszCwd = pszValue; 11922 break; 11923 case 's': 11924 pCur->pszSpecialEnv = pszValue; 11925 break; 11926 case 'e': 11927 pCur->pszExecutable = pszValue; 11928 break; 11929 case 'P': 11930 *piState = 1; 11931 if (*pszArg) 11932 return kwErrPrintfRc(2, "Option -P cannot be followed by other options!\n"); 11933 break; 11934 case 'R': 11935 pCur->cRuns = atoi(pszValue); 11936 if ((int)pCur->cRuns < 0) 11937 return kwErrPrintfRc(2, "Option -R takes a positive (or zero) integer as value: %s\n", pszValue); 11938 break; 11939 case '@': 11940 if (cRecursions < 5) 11941 { 11942 char *pszLeaked = NULL; 11943 int cArgs = 0; 11944 char **papszArgsLeaked = kwFullTestLoadArgvFile(pszValue, &cArgs, &pszLeaked); 11945 if (papszArgsLeaked) 11946 { 11947 rc = kwFullTestRunParseArgs(ppHead, piState, cArgs, papszArgsLeaked, pszDefaultCwd, 11948 cRecursions + 1, pszValue); 11949 pCur = *ppHead; 11950 } 11951 else 11952 return 2; 11953 } 11954 else 11955 return kwErrPrintfRc(2, "Too deep response file nesting!\n"); 11956 break; 11957 } 11958 11959 /* next */ 11960 ch = *pszArg++; 11961 } 11962 } 11963 else if (*piState == 2) 11964 rc = kwFullTestVectorAppend(&pCur->papszArgs, &pCur->cArgs, pszArg); 11965 else if (*piState == 1) 11966 { 11967 if (pszArg[0] != '-' || pszArg[1] != '-' || pszArg[2] != '\0') 11968 rc = kwFullTestVectorAppend(&pCur->papszPostCmdArgs, &pCur->cPostCmdArgs, pszArg); 11969 else 11970 *piState = 2; 11971 } 11972 else 11973 return kwErrPrintfRc(2, "Unexpected argument: %s\n", pszArg); 11974 if (rc) 11975 return rc; 11976 pCur->fVirgin = K_FALSE; 11977 } 11978 return 0; 11979 } 11980 11981 11982 /** 11983 * Handles what comes after --full-test. 11984 * 11985 * @returns Exit code. 11986 * @param argc Number of arguments after --full-test. 11987 * @param argv Arguments after --full-test. 11988 */ 11989 static int kwFullTestRun(int argc, char **argv) 11990 { 11991 char szDefaultCwd[MAX_PATH]; 11992 const char *pszDefaultCwd = getcwd(szDefaultCwd, sizeof(szDefaultCwd)); 11993 KWONETEST FirstTest; 11994 PKWONETEST pHead = &FirstTest; 11995 PKWONETEST pCur; 11996 int iState = 0; 11997 int rcExit; 11998 11999 /* 12000 * Parse arguments. 12001 */ 12002 kHlpMemSet(&FirstTest, 0, sizeof(FirstTest)); 12003 FirstTest.pszJobSrc = "command-line"; 12004 FirstTest.iJobSrc = 1; 12005 FirstTest.fVirgin = K_TRUE; 12006 FirstTest.pszCwd = pszDefaultCwd; 12007 FirstTest.cRuns = 1; 12008 12009 rcExit = kwFullTestRunParseArgs(&pHead, &iState, argc, argv, pszDefaultCwd, 0, "command-line"); 12010 if (rcExit) 12011 return rcExit; 12012 12013 /* 12014 * Do the job. LIFO ordering (see kSubmit). 12015 */ 12016 for (pCur = pHead; pCur; pCur = pCur->pNext) 12017 { 12018 if (!pCur->pszExecutable && pCur->papszArgs) 12019 pCur->pszExecutable = pCur->papszArgs[0]; 12020 if ( pCur->pszExecutable 12021 && pCur->cArgs > 0 12022 && pCur->cEnvVars > 0) 12023 { 12024 size_t const cbEnvVarCopy = sizeof(pCur->papszEnvVars[0]) * (pCur->cEnvVars + 1); 12025 char ** const papszEnvVarsCopy = (char **)kHlpDup(pCur->papszEnvVars, cbEnvVarCopy); 12026 unsigned iRun; 12027 12028 for (iRun = 0; iRun < pCur->cRuns; iRun++) 12029 { 12030 rcExit = kSubmitHandleJobUnpacked(pCur->pszExecutable, pCur->pszCwd, 12031 pCur->cArgs, pCur->papszArgs, pCur->fWatcomBrainDamange, 12032 pCur->cEnvVars, pCur->papszEnvVars, pCur->pszSpecialEnv, 12033 pCur->fNoPchCaching, pCur->cPostCmdArgs, pCur->papszPostCmdArgs); 12034 12035 KW_LOG(("rcExit=%d\n", rcExit)); 12036 kwSandboxCleanupLate(&g_Sandbox); 12037 12038 memcpy((void *)pCur->papszEnvVars, papszEnvVarsCopy, cbEnvVarCopy); 12039 } 12040 kHlpFree(papszEnvVarsCopy); 12041 } 12042 else 12043 rcExit = kwErrPrintfRc(2, "Job is underspecified! %s%s%s (Job started with argument #%u, %s)\n", 12044 pCur->pszExecutable ? "" : " No executable!", 12045 pCur->cArgs < 1 ? " No arguments!" : "", 12046 pCur->cEnvVars < 1 ? " No environment!" : "", 12047 pCur->iJobSrc, pCur->pszJobSrc); 10974 12048 } 10975 12049 … … 11167 12241 else if (strcmp(argv[i], "--test") == 0) 11168 12242 return kwTestRun(argc - i - 1, &argv[i + 1]); 12243 else if (strcmp(argv[i], "--full-test") == 0) 12244 return kwFullTestRun(argc - i - 1, &argv[i + 1]); 11169 12245 else if (strcmp(argv[i], "--priority") == 0) 11170 12246 { -
trunk/src/kmk/kmkbuiltin/kSubmit.c
r3224 r3313 121 121 int fdSocket; 122 122 #endif 123 124 /** Current history index (must mod with aHistory element count). */ 125 unsigned iHistory; 126 /** History. */ 127 struct 128 { 129 /** Pointer to the message, NULL if none. */ 130 void *pvMsg; 131 /** The message size, zero if not present. */ 132 size_t cbMsg; 133 } aHistory[4]; 123 134 124 135 /** What it's busy with. NULL if idle. */ … … 181 192 182 193 #ifdef KBUILD_OS_WINDOWS 194 /** The processor group allocator state. */ 195 static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator; 196 # if K_ARCH_BITS == 64 197 /** The processor group allocator state for 32-bit processes. */ 198 static MKWINCHILDCPUGROUPALLOCSTATE g_SubmitProcessorGroupAllocator32; 199 # endif 200 #endif 201 202 #ifdef KBUILD_OS_WINDOWS 183 203 /** Pointer to kernel32!SetThreadGroupAffinity. */ 184 204 static BOOL (WINAPI *g_pfnSetThreadGroupAffinity)(HANDLE, const GROUP_AFFINITY*, GROUP_AFFINITY *); … … 428 448 { 429 449 #ifdef KBUILD_OS_WINDOWS 430 static DWORD s_fDenyRemoteClients = ~(DWORD)0; 431 wchar_t wszPipeName[128]; 432 HANDLE hWorkerPipe; 433 int iProcessorGroup = -1; /** @todo determine process group. */ 450 static DWORD s_fDenyRemoteClients = ~(DWORD)0; 451 wchar_t wszPipeName[128]; 452 HANDLE hWorkerPipe; 453 int iProcessorGroup; 454 455 # if K_ARCH_BITS == 64 456 /** @todo make it return -1 if not applicable (e.g only one group). */ 457 if (pWorker->cBits != 32) 458 iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator); 459 else 460 iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator32); 461 # else 462 iProcessorGroup = MkWinChildAllocateCpuGroup(&g_SubmitProcessorGroupAllocator); 463 # endif 434 464 435 465 /* … … 464 494 { 465 495 extern int process_priority; /* main.c */ 466 wchar_t wszCommandLine[MAX_PATH * 3 ];496 wchar_t wszCommandLine[MAX_PATH * 3 + 32]; 467 497 wchar_t *pwszDst = wszCommandLine; 468 498 size_t cwcDst = K_ELEMENTS(wszCommandLine); … … 490 520 cwcDst -= cwc; 491 521 } 522 if (iProcessorGroup >= 0) 523 { 524 cwc = _snwprintf(pwszDst, cwcDst, L" --group %d", iProcessorGroup); 525 assert(cwc > 0 && cwc < cwcDst); 526 pwszDst += cwc; 527 cwcDst -= cwc; 528 } 492 529 *pwszDst = '\0'; 493 530 … … 549 586 warnx(pCtx, "warning: failed to set kWorker thread priority: %u\n", GetLastError()); 550 587 551 if (iProcessorGroup >= 0 )588 if (iProcessorGroup >= 0 && g_pfnSetThreadGroupAffinity) 552 589 { 553 590 GROUP_AFFINITY NewAff = { ~(uintptr_t)0, (WORD)iProcessorGroup, 0, 0, 0 }; … … 789 826 * @param fWatcomBrainDamage The wcc/wcc386 workaround. 790 827 * @param fNoPchCaching Whether to disable precompiled header caching. 828 * @param pszSpecialEnv Environment variable (name=value) subject to 829 * special expansion in kWorker. NULL if none. 791 830 * @param papszPostCmdArgs The post command and it's arguments. 792 831 * @param cPostCmdArgs Number of post command argument, including the … … 795 834 */ 796 835 static void *kSubmitComposeJobMessage(const char *pszExecutable, char **papszArgs, char **papszEnvVars, 797 const char *pszCwd, int fWatcomBrainDamage, int fNoPchCaching, 836 const char *pszCwd, int fWatcomBrainDamage, int fNoPchCaching, const char *pszSpecialEnv, 798 837 char **papszPostCmdArgs, uint32_t cPostCmdArgs, uint32_t *pcbMsg) 799 838 { 800 839 size_t cbTmp; 840 size_t cbSpecialEnv; 801 841 uint32_t i; 802 842 uint32_t cbMsg; … … 833 873 cbMsg += 1; /* fNoPchCaching */ 834 874 875 cbSpecialEnv = pszSpecialEnv ? strchr(pszSpecialEnv, '=') - pszSpecialEnv : 0; 876 cbMsg += cbSpecialEnv + 1; 877 835 878 cbMsg += sizeof(cPostCmdArgs); 836 879 for (i = 0; i < cPostCmdArgs; i++) … … 858 901 pbCursor += cbTmp; 859 902 860 /* argument */903 /* arguments */ 861 904 memcpy(pbCursor, &cArgs, sizeof(cArgs)); 862 905 pbCursor += sizeof(cArgs); … … 884 927 *pbCursor++ = fWatcomBrainDamage != 0; 885 928 *pbCursor++ = fNoPchCaching != 0; 929 930 /* Special environment variable name. */ 931 memcpy(pbCursor, pszSpecialEnv, cbSpecialEnv); 932 pbCursor += cbSpecialEnv; 933 *pbCursor++ = '\0'; 886 934 887 935 /* post command */ … … 1108 1156 #endif /* KBUILD_OS_WINDOWS */ 1109 1157 1158 1159 /** 1160 * Adds the given message to the history. 1161 * 1162 * @returns Pointer to old message, or NULL if no old msg to free. 1163 * @param pWorker The worker instance. 1164 * @param pvMsg The message. 1165 * @param cbMsg The message size. 1166 */ 1167 static void *kSubmitUpdateHistory(PWORKERINSTANCE pWorker, void *pvMsg, size_t cbMsg) 1168 { 1169 unsigned iHistory = pWorker->iHistory % K_ELEMENTS(pWorker->aHistory); 1170 void *pvRet; 1171 pWorker->iHistory++; 1172 pvRet = pWorker->aHistory[iHistory].pvMsg; 1173 pWorker->aHistory[iHistory].pvMsg = pvMsg; 1174 pWorker->aHistory[iHistory].cbMsg = cbMsg; 1175 return pvRet; 1176 } 1177 1178 typedef struct HISTORYDUMPBUF 1179 { 1180 char *pszBuf; 1181 size_t cbBuf; 1182 size_t off; 1183 PKMKBUILTINCTX pCtx; 1184 } HISTORYDUMPBUF; 1185 1186 1187 static void kSubmitDumpHistoryWrite(HISTORYDUMPBUF *pBuf, const char *pch, size_t cch) 1188 { 1189 if (pBuf->off + cch >= pBuf->cbBuf) 1190 { 1191 size_t cbNew = pBuf->cbBuf ? pBuf->cbBuf * 2 : 65536; 1192 while (pBuf->off + cch >= cbNew) 1193 cbNew *= 2; 1194 pBuf->pszBuf = (char *)xrealloc(pBuf->pszBuf, cbNew); 1195 pBuf->cbBuf = cbNew; 1196 } 1197 1198 memcpy(&pBuf->pszBuf[pBuf->off], pch, cch); 1199 pBuf->off += cch; 1200 pBuf->pszBuf[pBuf->off] = '\0'; 1201 } 1202 1203 static void kSubmitDumpHistoryPrintf(HISTORYDUMPBUF *pBuf, const char *pszFormat, ...) 1204 { 1205 char szTmp[32]; 1206 va_list va; 1207 va_start(va, pszFormat); 1208 for (;;) 1209 { 1210 const char *pszPct = strchr(pszFormat, '%'); 1211 if (!pszPct) 1212 { 1213 kSubmitDumpHistoryWrite(pBuf, pszFormat, strlen(pszFormat)); 1214 return; 1215 } 1216 if (pszPct != pszFormat) 1217 { 1218 kSubmitDumpHistoryWrite(pBuf, pszFormat, pszPct - pszFormat); 1219 pszFormat = pszPct; 1220 } 1221 pszFormat++; 1222 switch (*pszFormat++) 1223 { 1224 case 's': 1225 { 1226 const char * const psz = va_arg(va, const char *); 1227 size_t const cch = strlen(psz); 1228 if (memchr(psz, '\'', cch)) 1229 { 1230 kSubmitDumpHistoryWrite(pBuf, TUPLE("\"")); /** @todo what if there are '"' in the string? */ 1231 kSubmitDumpHistoryWrite(pBuf, psz, cch); 1232 kSubmitDumpHistoryWrite(pBuf, TUPLE("\"")); 1233 } 1234 else if ( !memchr(psz, ' ', cch) 1235 && !memchr(psz, '\t', cch) 1236 && !memchr(psz, '\n', cch) 1237 && !memchr(psz, '\r', cch) 1238 && !memchr(psz, '&', cch) 1239 && !memchr(psz, ';', cch) 1240 && !memchr(psz, '|', cch)) 1241 kSubmitDumpHistoryWrite(pBuf, psz, cch); 1242 else 1243 { 1244 kSubmitDumpHistoryWrite(pBuf, TUPLE("'")); 1245 kSubmitDumpHistoryWrite(pBuf, psz, strlen(psz)); 1246 kSubmitDumpHistoryWrite(pBuf, TUPLE("'")); 1247 } 1248 break; 1249 } 1250 1251 case 'd': 1252 { 1253 int iValue = va_arg(va, int); 1254 kSubmitDumpHistoryWrite(pBuf, szTmp, snprintf(szTmp, sizeof(szTmp), "%d", iValue)); 1255 break; 1256 } 1257 1258 case 'u': 1259 { 1260 unsigned uValue = va_arg(va, unsigned); 1261 kSubmitDumpHistoryWrite(pBuf, szTmp, snprintf(szTmp, sizeof(szTmp), "%u", uValue)); 1262 break; 1263 } 1264 1265 case '%': 1266 kSubmitDumpHistoryWrite(pBuf, "%s", 1); 1267 break; 1268 1269 default: 1270 assert(0); 1271 } 1272 } 1273 va_end(va); 1274 } 1275 1276 static void kSubmitDumpHistoryFlush(HISTORYDUMPBUF *pBuf) 1277 { 1278 if (pBuf->off > 0) 1279 output_write_text(pBuf->pCtx->pOut, 1, pBuf->pszBuf, pBuf->off); 1280 pBuf->off = 0; 1281 } 1282 1283 /** 1284 * Dumps the history for this worker to stderr in the given context. 1285 * 1286 * @param pCtx The command execution context. (Typically not a 1287 * real context.) 1288 * @param pWorker The worker instance. 1289 */ 1290 static void kSubmitDumpHistory(PKMKBUILTINCTX pCtx, PWORKERINSTANCE pWorker) 1291 { 1292 HISTORYDUMPBUF Buf = { NULL, 0, 0, pCtx }; 1293 int iHistory = pWorker->iHistory; 1294 unsigned cDumped = 0; 1295 1296 while (cDumped < K_ELEMENTS(pWorker->aHistory) && iHistory > 0) 1297 { 1298 unsigned const idx = (unsigned)--iHistory % K_ELEMENTS(pWorker->aHistory); 1299 const char *pszMsg = (const char *)pWorker->aHistory[idx].pvMsg; 1300 ssize_t cbMsg = pWorker->aHistory[idx].cbMsg; 1301 const char *pszExe; 1302 const char *pszCwd; 1303 uint32_t i; 1304 uint32_t cArgs; 1305 const char *pszArgs; 1306 size_t cbArgs; 1307 uint32_t cEnvVars; 1308 const char *pszEnvVars; 1309 size_t cbEnvVars; 1310 const char *pszSpecialEnv; 1311 char fNoPchCaching; 1312 char fWatcomBrainDamage; 1313 uint32_t cPostArgs; 1314 const char *pszPostArgs; 1315 size_t cbPostArgs; 1316 1317 cDumped++; 1318 if (!pszMsg || !cbMsg) 1319 break; 1320 1321 #define SKIP_BYTES(a_cbSkip) do { pszMsg += (a_cbSkip); cbMsg -= (a_cbSkip); } while (0) 1322 #define SKIP_STR() do { size_t const cbToSkip = strlen(pszMsg) + 1; SKIP_BYTES(cbToSkip); } while (0) 1323 #define SKIP_STRING_ARRAY(a_cStrings, a_cbPreable) do { \ 1324 for (i = 0; i < (a_cStrings) && cbMsg > 0; i++) { \ 1325 size_t const cbToSkip = (a_cbPreable) + strlen(pszMsg + (a_cbPreable)) + 1; \ 1326 SKIP_BYTES(cbToSkip); \ 1327 } } while (0) 1328 1329 /* Decode it: */ 1330 SKIP_BYTES(sizeof(uint32_t) + sizeof("JOB")); 1331 pszExe = pszMsg; 1332 SKIP_STR(); 1333 pszCwd = pszMsg; 1334 SKIP_STR(); 1335 1336 cArgs = *(uint32_t *)pszMsg; 1337 SKIP_BYTES(sizeof(uint32_t)); 1338 pszArgs = pszMsg; 1339 SKIP_STRING_ARRAY(cArgs, 1 /*fbFlags*/); 1340 cbArgs = pszMsg - pszArgs; 1341 1342 cEnvVars = *(uint32_t *)pszMsg; 1343 SKIP_BYTES(sizeof(uint32_t)); 1344 pszEnvVars = pszMsg; 1345 SKIP_STRING_ARRAY(cEnvVars, 0); 1346 cbEnvVars = pszMsg - pszEnvVars; 1347 1348 fWatcomBrainDamage = pszMsg[0] != '\0'; 1349 fNoPchCaching = pszMsg[1] != '\0'; 1350 SKIP_BYTES(2); 1351 1352 pszSpecialEnv = pszMsg; 1353 SKIP_STR(); 1354 1355 cPostArgs = *(uint32_t *)pszMsg; 1356 SKIP_BYTES(sizeof(uint32_t)); 1357 pszPostArgs = pszMsg; 1358 SKIP_STRING_ARRAY(cPostArgs, 0); 1359 cbPostArgs = pszMsg - pszPostArgs; 1360 1361 /* Produce parseable output: */ 1362 kSubmitDumpHistoryPrintf(&Buf, "kWorker %u/%u:\n\tkSubmit", (long)pWorker->pid, iHistory, pszExe); 1363 if (fNoPchCaching) 1364 kSubmitDumpHistoryWrite(&Buf, TUPLE(" --no-pch-caching")); 1365 if (fWatcomBrainDamage) 1366 kSubmitDumpHistoryWrite(&Buf, TUPLE(" --watcom-brain-damage")); 1367 if (pszSpecialEnv) 1368 kSubmitDumpHistoryPrintf(&Buf, " --special-env %s", pszSpecialEnv); 1369 kSubmitDumpHistoryPrintf(&Buf, " --chdir %s \\\n", pszCwd); 1370 1371 pszMsg = pszEnvVars; 1372 cbMsg = cbEnvVars; 1373 for (i = 0; i < cEnvVars && cbMsg > 0; i++) 1374 { 1375 kSubmitDumpHistoryPrintf(&Buf, "\t--putenv %s \\\n", pszMsg); 1376 SKIP_STR(); 1377 } 1378 1379 if (cPostArgs > 0) 1380 { 1381 kSubmitDumpHistoryWrite(&Buf, TUPLE("\t--post-cmd ")); 1382 pszMsg = pszPostArgs; 1383 cbMsg = cbPostArgs; 1384 for (i = 0; i < cPostArgs && cbMsg > 0; i++) 1385 { 1386 kSubmitDumpHistoryPrintf(&Buf, " %s", pszMsg); 1387 SKIP_STR(); 1388 } 1389 kSubmitDumpHistoryWrite(&Buf, TUPLE(" \\\n")); 1390 } 1391 kSubmitDumpHistoryWrite(&Buf, TUPLE("\t-- \\\n")); 1392 1393 pszMsg = pszArgs; 1394 cbMsg = cbArgs; 1395 for (i = 0; i < cArgs && cbMsg > 0; i++) 1396 { 1397 SKIP_BYTES(1); 1398 kSubmitDumpHistoryPrintf(&Buf, i + 1 < cArgs ? "\t%s \\\n" : "\t%s\n", pszMsg); 1399 SKIP_STR(); 1400 } 1401 1402 #undef SKIP_BYTES 1403 #undef SKIP_STR 1404 #undef SKIP_STRING_ARRAY 1405 } 1406 1407 kSubmitDumpHistoryFlush(&Buf); 1408 free(Buf.pszBuf); 1409 } 1410 1411 1110 1412 /** 1111 1413 * Marks the worker active. … … 1168 1470 if (pWorker->Result.s.bWorkerExiting) 1169 1471 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); 1472 if (pWorker->Result.s.rcExit && 1) 1473 kSubmitDumpHistory(pCtx, pWorker); 1170 1474 *pPidSpawned = 0; 1171 1475 return pWorker->Result.s.rcExit; … … 1247 1551 case STATUS_ILLEGAL_INSTRUCTION: *piSigNo = SIGILL; break; 1248 1552 } 1553 if (pWorker->Result.s.rcExit && 1) 1554 kSubmitDumpHistory(pCtx, pWorker); 1249 1555 if (pWorker->Result.s.bWorkerExiting) 1250 1556 kSubmitCloseConnectOnExitingWorker(pCtx, pWorker); … … 1410 1716 "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n" 1411 1717 " [-A|--append <var=val>] [-D|--prepend <var=val>]\n" 1412 " [-C|--chdir <dir>] [--wcc-brain-damage] [--no-pch-caching]\n" 1413 " [-3|--32-bit] [-6|--64-bit] [-v]\n" 1718 " [-s|--special-env <var=val>] [-C|--chdir <dir>]\n" 1719 " [--wcc-brain-damage] [--no-pch-caching]\n" 1720 " [-3|--32-bit] [-6|--64-bit] [-v] [--debug-dump-history]\n" 1414 1721 " [-P|--post-cmd <cmd> [args]] -- <program> [args]\n" 1415 1722 " or: %s --help\n" … … 1420 1727 " Zaps the environment. Position dependent.\n" 1421 1728 " -E, --set <var>=[value]\n" 1422 " Sets an envi ornment variable putenv fashion. Position dependent.\n"1729 " Sets an environment variable putenv fashion. Position dependent.\n" 1423 1730 " -U, --unset <var>\n" 1424 1731 " Removes an environment variable. Position dependent.\n" … … 1427 1734 " -D,--prepend <var>=<value>\n" 1428 1735 " Prepends the given value to the environment variable.\n" 1736 " -s,--special-env <var>=<value>\n" 1737 " Same as --set, but flags the variable for further expansion\n" 1738 " within kWorker. Replacements:\n" 1739 " @@PROCESSOR_GROUP@@ - The processor group number.\n" 1740 " @@AUTHENTICATION_ID@@ - The authentication ID from the process token.\n" 1741 " @@PID@@ - The kWorker process ID.\n" 1742 " @@@@ - Escaped \"@@\".\n" 1743 " @@DEBUG_COUNTER@@ - An ever increasing counter (starts at zero).\n" 1429 1744 " -C, --chdir <dir>\n" 1430 1745 " Specifies the current directory for the program. Relative paths\n" … … 1441 1756 " -v,--verbose\n" 1442 1757 " More verbose execution.\n" 1758 " --debug-dump-history\n" 1759 " Dump the history as of the submitted command. Handy for debuging\n" 1760 " trouble caused by a previous job.\n" 1443 1761 " -P|--post-cmd <cmd> ...\n" 1444 1762 " For running a built-in command on the output, specifying the command\n" … … 1458 1776 int kmk_builtin_kSubmit(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx, struct child *pChild, pid_t *pPidSpawned) 1459 1777 { 1778 #ifdef KBUILD_OS_WINDOWS 1779 static int s_fInitialized = 0; 1780 #endif 1460 1781 int rcExit = 0; 1461 1782 int iArg; … … 1464 1785 char **papszEnvVars; 1465 1786 const char *pszExecutable = NULL; 1787 const char *pszSpecialEnv = NULL; 1466 1788 int iPostCmd = argc; 1467 1789 int cPostCmdArgs = 0; … … 1469 1791 int fWatcomBrainDamage = 0; 1470 1792 int fNoPchCaching = 0; 1793 int fDebugDumpHistory = 0; 1471 1794 int cVerbosity = 0; 1472 1795 size_t const cbCwdBuf = GET_PATH_MAX; 1473 1796 PATH_VAR(szCwd); 1797 1798 #ifdef KBUILD_OS_WINDOWS 1799 /* 1800 * First time thru we must perform some initializations. 1801 */ 1802 if (s_fInitialized) 1803 { } 1804 else 1805 { 1806 MkWinChildInitCpuGroupAllocator(&g_SubmitProcessorGroupAllocator); 1807 # if K_ARCH_BITS == 64 1808 MkWinChildInitCpuGroupAllocator(&g_SubmitProcessorGroupAllocator32); 1809 # endif 1810 *(FARPROC *)&g_pfnSetThreadGroupAffinity = GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"), "SetThreadGroupAffinity"); 1811 s_fInitialized = 1; 1812 } 1813 #endif 1474 1814 1475 1815 /* … … 1533 1873 } 1534 1874 1875 if (strcmp(pszArg, "debug-dump-history") == 0) 1876 { 1877 fDebugDumpHistory = 1; 1878 continue; 1879 } 1880 1881 1535 1882 /* convert to short. */ 1536 1883 if (strcmp(pszArg, "help") == 0) … … 1551 1898 else if (strcmp(pszArg, "chdir") == 0) 1552 1899 chOpt = 'C'; 1900 else if (strcmp(pszArg, "set-special") == 0) 1901 chOpt = 's'; 1553 1902 else if (strcmp(pszArg, "post-cmd") == 0) 1554 1903 chOpt = 'P'; … … 1581 1930 case 'D': 1582 1931 case 'e': 1932 case 's': 1583 1933 if (*pszArg != '\0') 1584 1934 pszValue = pszArg + (*pszArg == ':' || *pszArg == '='); … … 1628 1978 case 'C': 1629 1979 rcExit = kBuiltinOptChDir(pCtx, szCwd, cbCwdBuf, pszValue); 1980 if (rcExit == 0) 1981 break; 1982 return rcExit; 1983 1984 case 's': 1985 if (pszSpecialEnv) 1986 return errx(pCtx, 1, "The -s option can only be used once!"); 1987 pszSpecialEnv = pszValue; 1988 rcExit = kBuiltinOptEnvSet(pCtx, &papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue); 1630 1989 if (rcExit == 0) 1631 1990 break; … … 1687 2046 uint32_t cbMsg; 1688 2047 void *pvMsg = kSubmitComposeJobMessage(pszExecutable, &argv[iArg], papszEnvVars, szCwd, 1689 fWatcomBrainDamage, fNoPchCaching, 2048 fWatcomBrainDamage, fNoPchCaching, pszSpecialEnv, 1690 2049 &argv[iPostCmd], cPostCmdArgs, &cbMsg); 1691 2050 PWORKERINSTANCE pWorker = kSubmitSelectWorkSpawnNewIfNecessary(pCtx, cBitsWorker, cVerbosity); … … 1703 2062 rcExit = kSubmitSendJobMessage(pCtx, pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity); 1704 2063 if (rcExit == 0) 2064 { 2065 pvMsg = kSubmitUpdateHistory(pWorker, pvMsg, cbMsg); 2066 if (fDebugDumpHistory) 2067 kSubmitDumpHistory(pCtx, pWorker); 1705 2068 rcExit = kSubmitMarkActive(pCtx, pWorker, cVerbosity, pChild, pPidSpawned); 2069 } 1706 2070 1707 2071 if (!g_fAtExitRegistered) … … 1723 2087 } 1724 2088 1725 1726 -
trunk/src/kmk/w32/winchildren.c
r3224 r3313 334 334 /** Pointer to childcare workers. */ 335 335 static PWINCHILDCAREWORKER *g_papChildCareworkers = NULL; 336 /** The group index for the worker allocator. 337 * This is ever increasing and must be modded by g_cProcessorGroups. */ 338 static unsigned g_idxProcessorGroupAllocator = 0; 339 /** The processor in group index for the worker allocator. */ 340 static unsigned g_idxProcessorInGroupAllocator = 0; 336 /** The processor group allocator state. */ 337 static MKWINCHILDCPUGROUPALLOCSTATE g_ProcessorGroupAllocator; 341 338 /** Number of processor groups in the system. */ 342 339 static unsigned g_cProcessorGroups = 1; … … 468 465 pacProcessorsInGroup[iGroup] = g_pfnGetActiveProcessorCount(iGroup); 469 466 470 /* We shift the starting group with the make nesting level as part of 471 our very simple distribution strategy. */ 472 g_idxProcessorGroupAllocator = makelevel; 467 MkWinChildInitCpuGroupAllocator(&g_ProcessorGroupAllocator); 473 468 } 474 469 else … … 2635 2630 2636 2631 /** 2632 * Initializes the processor group allocator. 2633 * 2634 * @param pState The allocator to initialize. 2635 */ 2636 void MkWinChildInitCpuGroupAllocator(PMKWINCHILDCPUGROUPALLOCSTATE pState) 2637 { 2638 /* We shift the starting group with the make nesting level as part of 2639 our very simple distribution strategy. */ 2640 pState->idxGroup = makelevel; 2641 pState->idxProcessorInGroup = 0; 2642 } 2643 2644 /** 2645 * Allocate CPU group for the next child process. 2646 * 2647 * @returns CPU group. 2648 * @param pState The allocator state. Must be initialized by 2649 * MkWinChildInitCpuGroupAllocator(). 2650 */ 2651 unsigned int MkWinChildAllocateCpuGroup(PMKWINCHILDCPUGROUPALLOCSTATE pState) 2652 { 2653 unsigned int iGroup = 0; 2654 if (g_cProcessorGroups > 1) 2655 { 2656 unsigned int cMaxInGroup; 2657 unsigned int cInGroup; 2658 2659 iGroup = pState->idxGroup % g_cProcessorGroups; 2660 2661 /* Advance. We employ a very simple strategy that does 50% in 2662 each group for each group cycle. Odd processor counts are 2663 caught in odd group cycles. The init function selects the 2664 starting group based on make nesting level to avoid stressing 2665 out the first group. */ 2666 cInGroup = ++pState->idxProcessorInGroup; 2667 cMaxInGroup = g_pacProcessorsInGroup[iGroup]; 2668 if ( !(cMaxInGroup & 1) 2669 || !((pState->idxGroup / g_cProcessorGroups) & 1)) 2670 cMaxInGroup /= 2; 2671 else 2672 cMaxInGroup = cMaxInGroup / 2 + 1; 2673 if (cInGroup >= cMaxInGroup) 2674 { 2675 pState->idxProcessorInGroup = 0; 2676 pState->idxGroup++; 2677 } 2678 } 2679 return iGroup; 2680 } 2681 2682 /** 2637 2683 * Creates another childcare worker. 2638 2684 * … … 2654 2700 { 2655 2701 /* Before we start the thread, assign it to a processor group. */ 2656 if (g_cProcessorGroups > 1) 2657 { 2658 unsigned int cMaxInGroup; 2659 unsigned int cInGroup; 2660 unsigned int iGroup = g_idxProcessorGroupAllocator % g_cProcessorGroups; 2661 pWorker->iProcessorGroup = iGroup; 2662 2663 /* Advance. We employ a very simple strategy that does 50% in 2664 each group for each group cycle. Odd processor counts are 2665 caught in odd group cycles. The init function selects the 2666 starting group based on make nesting level to avoid stressing 2667 out the first group. */ 2668 cInGroup = ++g_idxProcessorInGroupAllocator; 2669 cMaxInGroup = g_pacProcessorsInGroup[iGroup]; 2670 if ( !(cMaxInGroup & 1) 2671 || !((g_idxProcessorGroupAllocator / g_cProcessorGroups) & 1)) 2672 cMaxInGroup /= 2; 2673 else 2674 cMaxInGroup = cMaxInGroup / 2 + 1; 2675 if (cInGroup >= cMaxInGroup) 2676 { 2677 g_idxProcessorInGroupAllocator = 0; 2678 g_idxProcessorGroupAllocator++; 2679 } 2680 } 2702 pWorker->iProcessorGroup = MkWinChildAllocateCpuGroup(&g_ProcessorGroupAllocator); 2681 2703 2682 2704 /* Try start the thread. */ … … 3414 3436 * that completed children is the typical source of these tokens (esp. for kmk). 3415 3437 * 3416 * @returns Zero if completedchildren, event handle if waiting is required.3438 * @returns Zero if no active children, event handle if waiting is required. 3417 3439 */ 3418 3440 intptr_t MkWinChildGetCompleteEventHandle(void) -
trunk/src/kmk/w32/winchildren.h
r3200 r3313 26 26 #ifndef INCLUDED_WINCHILDREN_H 27 27 #define INCLUDED_WINCHILDREN_H 28 29 /** Child processor group allocator state. */ 30 typedef struct MKWINCHILDCPUGROUPALLOCSTATE 31 { 32 /** The group index for the worker allocator. 33 * This is ever increasing and must be modded by g_cProcessorGroups. */ 34 unsigned int idxGroup; 35 /** The processor in group index for the worker allocator. */ 36 unsigned int idxProcessorInGroup; 37 } MKWINCHILDCPUGROUPALLOCSTATE; 38 /** Pointer to a CPU group allocator state. */ 39 typedef MKWINCHILDCPUGROUPALLOCSTATE *PMKWINCHILDCPUGROUPALLOCSTATE; 28 40 29 41 #ifdef DECLARE_HANDLE … … 68 80 int MkWinChildCreate(char **papszArgs, char **papszEnv, const char *pszShell, struct child *pMkChild, pid_t *pPid); 69 81 int MkWinChildCreateWithStdOutPipe(char **papszArgs, char **papszEnv, int fdErr, pid_t *pPid, int *pfdReadPipe); 82 void MkWinChildInitCpuGroupAllocator(PMKWINCHILDCPUGROUPALLOCSTATE pState); 83 unsigned int MkWinChildAllocateCpuGroup(PMKWINCHILDCPUGROUPALLOCSTATE pState); 84 70 85 #ifdef KMK 71 86 struct KMKBUILTINENTRY; … … 86 101 char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]); 87 102 # endif 88 #endif 103 #endif /* KMK */ 89 104 int MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild); 90 105 int MkWinChildWait(int fBlock, pid_t *pPid, int *piExitCode, int *piSignal, int *pfCoreDumped, struct child **ppMkChild);
Note:
See TracChangeset
for help on using the changeset viewer.