Changeset 3195 for trunk/src/kmk/w32


Ignore:
Timestamp:
Mar 27, 2018, 8:09:23 PM (7 years ago)
Author:
bird
Message:

kmk/win: Catch output from processes spawned by kmk_redirect. Made imagecase threadsafe and made winchildren use it.

Location:
trunk/src/kmk/w32
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/w32/imagecache.c

    r3140 r3195  
    2626/* No GNU coding style here! */
    2727
    28 /*******************************************************************************
    29 *   Header Files                                                               *
    30 *******************************************************************************/
     28/*********************************************************************************************************************************
     29*   Header Files                                                                                                                 *
     30*********************************************************************************************************************************/
    3131#include "makeint.h"
    3232
     
    3434
    3535
    36 /*******************************************************************************
    37 *   Structures and Typedefs                                                    *
    38 *******************************************************************************/
     36/*********************************************************************************************************************************
     37*   Structures and Typedefs                                                                                                      *
     38*********************************************************************************************************************************/
    3939typedef struct EXECCACHEENTRY
    4040{
     
    4242    unsigned                uHash;
    4343    /** The name length. */
    44     unsigned                cchName;
     44    unsigned                cwcName;
    4545    /** Pointer to the next name with the same hash. */
    4646    struct EXECCACHEENTRY  *pNext;
    4747    /** When it was last referenced. */
    4848    unsigned                uLastRef;
    49     /** The module handle. */
     49    /** The module handle, LOAD_LIBRARY_AS_DATAFILE. */
    5050    HMODULE                 hmod1;
    51     /** The module handle. */
     51    /** The module handle, DONT_RESOLVE_DLL_REFERENCES. */
    5252    HMODULE                 hmod2;
    5353    /** The executable path. */
    54     char                    szName[1];
     54    wchar_t                 wszName[1];
    5555} EXECCACHEENTRY;
    5656typedef EXECCACHEENTRY *PEXECCACHEENTRY;
    5757
    58 /*******************************************************************************
    59 *   Global Variables                                                           *
    60 *******************************************************************************/
     58
     59/*********************************************************************************************************************************
     60*   Global Variables                                                                                                             *
     61*********************************************************************************************************************************/
     62/** Critical section serializing all access. */
     63static CRITICAL_SECTION g_CritSect;
     64/** Set if initialized. */
     65static int volatile     g_fInitialized = 0;
    6166/** The number of cached images. */
    6267static unsigned         g_cCached;
     
    6974/** The hash table. */
    7075static PEXECCACHEENTRY  g_apHashTab[EXECCACHE_HASHTAB_SIZE];
     76
     77
     78/** A sleepy approach to do-once. */
     79static void kmk_cache_lazy_init(void)
     80{
     81    if (_InterlockedCompareExchange(&g_fInitialized, -1, 0) == 0)
     82    {
     83        InitializeCriticalSection(&g_CritSect);
     84        _InterlockedExchange(&g_fInitialized, 1);
     85    }
     86    else
     87        while (g_fInitialized != 1)
     88            Sleep(1);
     89}
    7190
    7291
     
    83102   elsewhere. */
    84103
    85 static unsigned execcache_calc_hash(const char *psz, unsigned *pcch)
    86 {
    87     unsigned char  *puch = (unsigned char *)psz;
    88     unsigned        hash = 0;
    89     int             ch;
    90 
    91     while ((ch = *puch++))
     104static unsigned execcache_calc_hash(const wchar_t *pwsz, size_t *pcch)
     105{
     106    wchar_t const  * const pwszStart = pwsz;
     107    unsigned               hash = 0;
     108    int                    ch;
     109
     110    while ((ch = *pwsz++) != L'\0')
    92111        hash = ch + (hash << 6) + (hash << 16) - hash;
    93112
    94     *pcch = (unsigned)(puch - psz - 1);
     113    *pcch = (size_t)(pwsz - pwszStart - 1);
    95114    return hash;
    96115}
    97116
    98 
    99 extern void kmk_cache_exec_image(const char *pszExec)
    100 {
    101     /*
    102      * Lookup the name.
    103      */
    104     unsigned            cchName;
    105     const unsigned      uHash = execcache_calc_hash(pszExec, &cchName);
     117/**
     118 * Caches two memory mappings of the specified image so that it isn't flushed
     119 * from the kernel's cache mananger.
     120 *
     121 * Not sure exactly how much this actually helps, but whatever...
     122 *
     123 * @param   pwszExec    The executable.
     124 */
     125extern void kmk_cache_exec_image_w(const wchar_t *pwszExec)
     126{
     127    /*
     128     * Prepare name lookup and to lazy init.
     129     */
     130    size_t              cwcName;
     131    const unsigned      uHash = execcache_calc_hash(pwszExec, &cwcName);
    106132    PEXECCACHEENTRY    *ppCur = &g_apHashTab[uHash % EXECCACHE_HASHTAB_SIZE];
    107     PEXECCACHEENTRY     pCur  = *ppCur;
     133    PEXECCACHEENTRY     pCur;
     134
     135    if (g_fInitialized != 1)
     136        kmk_cache_lazy_init();
     137
     138    /*
     139     * Do the lookup.
     140     */
     141    EnterCriticalSection(&g_CritSect);
     142    pCur = *ppCur;
    108143    while (pCur)
    109144    {
    110145        if (   pCur->uHash   == uHash
    111             && pCur->cchName == cchName
    112             && !memcmp(pCur->szName, pszExec, cchName))
     146            && pCur->cwcName == cwcName
     147            && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t)))
    113148        {
    114149            pCur->uLastRef = ++g_uNow;
     150            LeaveCriticalSection(&g_CritSect);
    115151            return;
    116152        }
     
    118154        pCur = pCur->pNext;
    119155    }
     156    LeaveCriticalSection(&g_CritSect);
    120157
    121158    /*
    122159     * Not found, create a new entry.
    123160     */
    124     pCur = xmalloc(sizeof(*pCur) + cchName);
     161    pCur = xmalloc(sizeof(*pCur) + cwcName * sizeof(wchar_t));
    125162    pCur->uHash    = uHash;
    126     pCur->cchName  = cchName;
     163    pCur->cwcName  = (unsigned)cwcName;
    127164    pCur->pNext    = NULL;
    128165    pCur->uLastRef = ++g_uNow;
    129     memcpy(pCur->szName, pszExec, cchName + 1);
    130     pCur->hmod1 = LoadLibraryEx(pszExec, NULL, LOAD_LIBRARY_AS_DATAFILE);
     166    memcpy(pCur->wszName, pwszExec, (cwcName + 1) * sizeof(wchar_t));
     167    pCur->hmod1 = LoadLibraryExW(pwszExec, NULL, LOAD_LIBRARY_AS_DATAFILE);
    131168    if (pCur->hmod1 != NULL)
    132         pCur->hmod2 = LoadLibraryEx(pszExec, NULL, DONT_RESOLVE_DLL_REFERENCES);
     169        pCur->hmod2 = LoadLibraryExW(pwszExec, NULL, DONT_RESOLVE_DLL_REFERENCES);
    133170    else
    134171        pCur->hmod2 = NULL;
    135172
    136     *ppCur = pCur;
    137     g_cCached++;
    138 }
    139 
     173    /*
     174     * Insert it.
     175     * Take into account that we might've been racing other threads,
     176     * fortunately we don't evict anything from the cache.
     177     */
     178    EnterCriticalSection(&g_CritSect);
     179    if (*ppCur != NULL)
     180    {
     181        /* Find new end of chain and check for duplicate. */
     182        PEXECCACHEENTRY pCur2 = *ppCur;
     183        while (pCur2)
     184        {
     185            if (   pCur->uHash   == uHash
     186                && pCur->cwcName == cwcName
     187                && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t)))
     188                break;
     189            ppCur = &pCur->pNext;
     190            pCur = pCur->pNext;
     191        }
     192
     193    }
     194    if (*ppCur == NULL)
     195    {
     196        *ppCur = pCur;
     197        g_cCached++;
     198        LeaveCriticalSection(&g_CritSect);
     199    }
     200    else
     201    {
     202        LeaveCriticalSection(&g_CritSect);
     203
     204        if (pCur->hmod1 != NULL)
     205            FreeLibrary(pCur->hmod1);
     206        if (pCur->hmod2 != NULL)
     207            FreeLibrary(pCur->hmod2);
     208        free(pCur);
     209    }
     210}
     211
     212extern void kmk_cache_exec_image_a(const char *pszExec)
     213{
     214    wchar_t wszExec[260];
     215    int cwc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszExec, strlen(pszExec) + 1, wszExec, 260);
     216    if (cwc > 0)
     217        kmk_cache_exec_image_w(wszExec);
     218}
     219
  • trunk/src/kmk/w32/subproc/sub_proc.c

    r3140 r3195  
    4040# include <assert.h>
    4141# include "kmkbuiltin.h"
    42 extern void kmk_cache_exec_image(const char *); /* imagecache.c */
     42extern void kmk_cache_exec_image_a(const char *); /* imagecache.c */
    4343#endif
    4444
     
    844844#ifdef KMK
    845845                if (exec_fname[0])
    846                         kmk_cache_exec_image(exec_fname);
     846                        kmk_cache_exec_image_a(exec_fname);
    847847                else if (exec_path)
    848                         kmk_cache_exec_image(exec_path);
     848                        kmk_cache_exec_image_a(exec_path);
    849849                else if (argv[0])
    850                         kmk_cache_exec_image(argv[0]);
     850                        kmk_cache_exec_image_a(argv[0]);
    851851
    852852                switch (process_priority) {
  • trunk/src/kmk/w32/winchildren.c

    r3192 r3195  
    101101
    102102#include "nt/nt_child_inject_standard_handles.h"
     103
     104#ifndef KMK_BUILTIN_STANDALONE
     105extern void kmk_cache_exec_image_w(const wchar_t *); /* imagecache.c */
     106#endif
    103107
    104108
     
    805809 * Commmon worker for waiting on a child process and retrieving the exit code.
    806810 *
     811 * @returns Child exit code.
    807812 * @param   pWorker             The worker.
    808813 * @param   pChild              The child.
     
    812817 *                              associated with the worker.
    813818 */
    814 static void mkWinChildcareWorkerWaitForProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, HANDLE hProcess,
    815                                                WCHAR const *pwszJob, BOOL fCatchOutput)
     819static int mkWinChildcareWorkerWaitForProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, HANDLE hProcess,
     820                                              WCHAR const *pwszJob, BOOL fCatchOutput)
    816821{
    817822    DWORD const msStart = GetTickCount();
     
    850855                    mkWinChildcareWorkerCatchOutput(pChild, &pWorker->StdErr, TRUE /*fFlushing*/);
    851856                }
    852                 return;
     857                return dwExitCode;
    853858            }
    854859        }
     
    891896        if (pChild->iExitCode == 0)
    892897            pChild->iExitCode = -4242;
    893         return;
     898        return pChild->iExitCode;
    894899    }
    895900}
     
    930935 * @param   pwszzEnvironment    The enviornment block.
    931936 */
    932 static int mkWinChildcareWorkerCreateProcess(PWINCHILDCAREWORKER pWorker, PWINCHILD pChild, WCHAR const *pwszImageName,
    933                                              WCHAR const *pwszCommandLine, WCHAR const *pwszzEnvironment)
     937static int mkWinChildcareWorkerCreateProcess(PWINCHILDCAREWORKER pWorker, WCHAR const *pwszImageName,
     938                                             WCHAR const *pwszCommandLine, WCHAR const *pwszzEnvironment, WCHAR const *pwszCwd,
     939                                             BOOL pafReplace[3], HANDLE pahChild[3], BOOL fCatchOutput, HANDLE *phProcess)
    934940{
    935941    PROCESS_INFORMATION ProcInfo;
    936942    STARTUPINFOW        StartupInfo;
    937943    DWORD               fFlags       = CREATE_UNICODE_ENVIRONMENT;
    938     BOOL const          fHaveHandles = pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE
    939                                     || pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE;
     944    BOOL const          fHaveHandles = pafReplace[0] | pafReplace[1] | pafReplace[2];
    940945    BOOL                fRet;
    941946    DWORD               dwErr;
     
    965970    StartupInfo.cbReserved2 = 0;
    966971    if (   !fHaveHandles
    967         && !pChild->u.Process.fCatchOutput)
     972        && !fCatchOutput)
    968973        StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES;
    969974    else
     
    9991004
    10001005    fRet = CreateProcessW((WCHAR *)pwszImageName, (WCHAR *)pwszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/,
    1001                           FALSE /*fInheritHandles*/, fFlags, (WCHAR *)pwszzEnvironment, NULL /*pwsz*/, &StartupInfo, &ProcInfo);
     1006                          FALSE /*fInheritHandles*/, fFlags, (WCHAR *)pwszzEnvironment, pwszCwd, &StartupInfo, &ProcInfo);
    10021007    dwErr = GetLastError();
    10031008
     
    10061011#endif
    10071012    if (fRet)
    1008         pChild->u.Process.hProcess = ProcInfo.hProcess;
     1013        *phProcess = ProcInfo.hProcess;
    10091014    else
    10101015    {
    10111016        fprintf(stderr, "CreateProcess(%ls) failed: %u\n", pwszImageName, dwErr);
    1012         return pChild->iExitCode = (int)dwErr;
     1017        return (int)dwErr;
    10131018    }
    10141019
     
    10221027         * First do handle inhertiance as that's the most complicated.
    10231028         */
    1024         if (fHaveHandles || pChild->u.Process.fCatchOutput)
    1025         {
    1026             char    szErrMsg[128];
    1027             BOOL    afReplace[3];
    1028             HANDLE  ahChild[3];
    1029 
    1030             afReplace[0] = FALSE;
    1031             ahChild[0]   = INVALID_HANDLE_VALUE;
    1032             if (fHaveHandles)
    1033             {
    1034                 afReplace[1] = pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE;
    1035                 ahChild[1]   = pChild->u.Process.hStdOut;
    1036                 afReplace[2] = pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE;
    1037                 ahChild[2]   = pChild->u.Process.hStdErr;
    1038             }
    1039             else
    1040             {
    1041                 afReplace[1] = TRUE;
    1042                 ahChild[1]   = pWorker->StdOut.hPipeChild;
    1043                 afReplace[2] = TRUE;
    1044                 ahChild[2]   = pWorker->StdErr.hPipeChild;
    1045             }
    1046 
    1047             dwErr = nt_child_inject_standard_handles(ProcInfo.hProcess, afReplace, ahChild, szErrMsg, sizeof(szErrMsg));
     1029        if (fHaveHandles || fCatchOutput)
     1030        {
     1031            char szErrMsg[128];
     1032            if (fCatchOutput)
     1033            {
     1034                if (!pafReplace[1])
     1035                {
     1036                    pafReplace[1] = TRUE;
     1037                    pahChild[1]   = pWorker->StdOut.hPipeChild;
     1038                }
     1039                if (!pafReplace[2])
     1040                {
     1041                    pafReplace[2] = TRUE;
     1042                    pahChild[2]   = pWorker->StdErr.hPipeChild;
     1043                }
     1044            }
     1045            dwErr = nt_child_inject_standard_handles(ProcInfo.hProcess, pafReplace, pahChild, szErrMsg, sizeof(szErrMsg));
    10481046            if (dwErr != 0)
    10491047                fprintf(stderr, "%s\n", szErrMsg);
     
    10941092
    10951093    /*
    1096      * Close unnecessary handles.
    1097      */
    1098     mkWinChildcareWorkerCloseStandardHandles(pChild);
     1094     * Close unnecessary handles and cache the image.
     1095     */
    10991096    CloseHandle(ProcInfo.hThread);
     1097    kmk_cache_exec_image_w(pwszImageName);
     1098    return 0;
     1099}
     1100
     1101/**
     1102 * Converts a argument vector that has already been quoted correctly.
     1103 *
     1104 * The argument vector is typically the result of quote_argv().
     1105 *
     1106 * @returns 0 on success, non-zero on failure.
     1107 * @param   papszArgs           The argument vector to convert.
     1108 * @param   ppwszCommandLine    Where to return the command line.
     1109 */
     1110static int mkWinChildcareWorkerConvertQuotedArgvToCommandline(char **papszArgs, WCHAR **ppwszCommandLine)
     1111{
     1112    WCHAR   *pwszCmdLine;
     1113    WCHAR   *pwszDst;
     1114
     1115    /*
     1116     * Calc length the converted length.
     1117     */
     1118    unsigned cwcNeeded = 1;
     1119    unsigned i = 0;
     1120    const char *pszSrc;
     1121    while ((pszSrc = papszArgs[i]) != NULL)
     1122    {
     1123        int cwcThis = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, -1, NULL, 0);
     1124        if (cwcThis > 0 || *pszSrc == '\0')
     1125            cwcNeeded += cwcThis + 1;
     1126        else
     1127        {
     1128            DWORD dwErr = GetLastError();
     1129            fprintf(stderr, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr);
     1130            return dwErr;
     1131        }
     1132        i++;
     1133    }
     1134
     1135    /*
     1136     * Allocate and do the conversion.
     1137     */
     1138    pwszCmdLine = pwszDst = (WCHAR *)xmalloc(cwcNeeded * sizeof(WCHAR));
     1139    i = 0;
     1140    while ((pszSrc = papszArgs[i]) != NULL)
     1141    {
     1142        int cwcThis;
     1143        if (i > 0)
     1144        {
     1145            *pwszDst++ = ' ';
     1146            cwcNeeded--;
     1147        }
     1148
     1149        cwcThis = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszSrc, -1, pwszDst, cwcNeeded);
     1150        if (!cwcThis && *pszSrc != '\0')
     1151        {
     1152            DWORD dwErr = GetLastError();
     1153            fprintf(stderr, _("MultiByteToWideChar failed to convert argv[%u] (%s): %u\n"), i, pszSrc, dwErr);
     1154            free(pwszCmdLine);
     1155            return dwErr;
     1156        }
     1157        if (cwcThis > 0 && pwszDst[cwcThis - 1] == '\0')
     1158            cwcThis--;
     1159        pwszDst += cwcThis;
     1160        cwcNeeded -= cwcThis;
     1161        i++;
     1162    }
     1163    *pwszDst++ = '\0';
     1164
     1165    *ppwszCommandLine = pwszCmdLine;
    11001166    return 0;
    11011167}
     
    17071773        {
    17081774            fprintf(stderr, "%s: not found!\n", pszArg0);
    1709 //__debugbreak();
    17101775            dwErr = ERROR_FILE_NOT_FOUND;
    17111776        }
     
    19201985        if (rc == 0)
    19211986        {
    1922             rc = mkWinChildcareWorkerCreateProcess(pWorker, pChild, pwszImageName, pwszCommandLine, pwszzEnvironment);
     1987            BOOL afReplace[3] = { FALSE, pChild->u.Process.hStdOut != INVALID_HANDLE_VALUE, pChild->u.Process.hStdErr != INVALID_HANDLE_VALUE };
     1988            HANDLE ahChild[3] = { INVALID_HANDLE_VALUE, pChild->u.Process.hStdOut, pChild->u.Process.hStdErr };
     1989            rc = mkWinChildcareWorkerCreateProcess(pWorker, pwszImageName, pwszCommandLine, pwszzEnvironment,
     1990                                                   NULL /*pwszCwd*/, afReplace, ahChild, pChild->u.Process.fCatchOutput,
     1991                                                   &pChild->u.Process.hProcess);
     1992            mkWinChildcareWorkerCloseStandardHandles(pChild);
    19231993            if (rc == 0)
    19241994            {
     
    19582028{
    19592029    PCKMKBUILTINENTRY pBuiltIn = pChild->u.BuiltIn.pBuiltIn;
    1960     KMKBUILTINCTX Ctx = { pBuiltIn->uName.s.sz, pChild->pMkChild ? &pChild->pMkChild->output : NULL };
     2030    KMKBUILTINCTX Ctx =
     2031    {
     2032        pBuiltIn->uName.s.sz,
     2033        pChild->pMkChild ? &pChild->pMkChild->output : NULL,
     2034        pWorker,
     2035    };
    19612036    if (pBuiltIn->uFnSignature == FN_SIG_MAIN)
    19622037        pChild->iExitCode = pBuiltIn->u.pfnMain(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs,
     
    19642039    else if (pBuiltIn->uFnSignature == FN_SIG_MAIN_SPAWNS)
    19652040        pChild->iExitCode = pBuiltIn->u.pfnMainSpawns(pChild->u.BuiltIn.cArgs, pChild->u.BuiltIn.papszArgs,
    1966                                                       pChild->u.BuiltIn.papszEnv, &Ctx, pChild->pMkChild, NULL);
     2041                                                      pChild->u.BuiltIn.papszEnv, &Ctx, pChild->pMkChild, NULL /*pPid*/);
    19672042    else
    19682043    {
     
    21152190                PWINCHILD pTailExpect;
    21162191
     2192                pWorker->pCurChild = pChild;
    21172193                switch (pChild->enmType)
    21182194                {
     
    21372213                        assert(0);
    21382214                }
     2215                pWorker->pCurChild = NULL;
    21392216
    21402217                /*
     
    28212898}
    28222899
     2900
     2901/**
     2902 * New interface used by redirect.c for spawning and waitin on a child.
     2903 *
     2904 * This interface is only used when kmk_builtin_redirect is already running on
     2905 * a worker thread.
     2906 *
     2907 * @returns exit status.
     2908 * @param   pvWorker        The worker instance.
     2909 * @param   pszExecutable   The executable image to run.
     2910 * @param   papszArgs       Argument vector.
     2911 * @param   fQuotedArgv     Whether the argument vector is already quoted and
     2912 *                          just need some space to be turned into a command
     2913 *                          line.
     2914 * @param   papszEnvVars    Environment vector.
     2915 * @param   pszCwd          The working directory of the child.  Optional.
     2916 * @param   pafReplace      Which standard handles to replace. Maybe modified!
     2917 * @param   pahReplace      The replacement handles.  Maybe modified!
     2918 *
     2919 */
     2920int MkWinChildBuiltInExecChild(void *pvWorker, const char *pszExecutable, char **papszArgs, BOOL fQuotedArgv,
     2921                               char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3])
     2922{
     2923    PWINCHILDCAREWORKER pWorker = (PWINCHILDCAREWORKER)pvWorker;
     2924    WCHAR              *pwszSearchPath   = NULL;
     2925    WCHAR              *pwszzEnvironment = NULL;
     2926    WCHAR              *pwszCommandLine  = NULL;
     2927    WCHAR              *pwszImageName    = NULL;
     2928    WCHAR              *pwszCwd          = NULL;
     2929    BOOL                fNeedShell       = FALSE;
     2930    int                 rc;
     2931    assert(pWorker->uMagic == WINCHILDCAREWORKER_MAGIC);
     2932    assert(pWorker->pCurChild != NULL && pWorker->pCurChild->uMagic == WINCHILD_MAGIC);
     2933
     2934    /*
     2935     * Convert the CWD first since it's optional and we don't need to clean
     2936     * up anything here if it fails.
     2937     */
     2938    if (pszCwd)
     2939    {
     2940        size_t cchCwd = strlen(pszCwd);
     2941        int    cwcCwd = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszCwd, cchCwd + 1, NULL, 0);
     2942        pwszCwd = xmalloc((cwcCwd + 1) * sizeof(WCHAR)); /* (+1 in case cwcCwd is 0) */
     2943        cwcCwd = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszCwd, cchCwd + 1, pwszCwd, cwcCwd + 1);
     2944        if (!cwcCwd)
     2945        {
     2946            rc = GetLastError();
     2947            fprintf(stderr, _("MultiByteToWideChar failed to convert CWD (%s): %u\n"), pszCwd, (unsigned)rc);
     2948            return rc;
     2949        }
     2950    }
     2951
     2952    /*
     2953     * Before we search for the image, we convert the environment so we don't
     2954     * have to traverse it twice to find the PATH.
     2955     */
     2956    rc = mkWinChildcareWorkerConvertEnvironment(papszEnvVars ? papszEnvVars : environ, 0/*cbEnvStrings*/,
     2957                                                &pwszzEnvironment, &pwszSearchPath);
     2958    /*
     2959     * Find the executable and maybe checking if it's a shell script, then
     2960     * convert it to a command line.
     2961     */
     2962    if (rc == 0)
     2963        rc = mkWinChildcareWorkerFindImage(pszExecutable, pwszSearchPath, pwszzEnvironment,
     2964                                           NULL /*pszNull*/, &pwszImageName, &fNeedShell);
     2965    if (rc == 0)
     2966    {
     2967        assert(!fNeedShell);
     2968        if (!fQuotedArgv)
     2969            rc = mkWinChildcareWorkerConvertCommandline(papszArgs, 0 /*fFlags*/, &pwszCommandLine);
     2970        else
     2971            rc = mkWinChildcareWorkerConvertQuotedArgvToCommandline(papszArgs, &pwszCommandLine);
     2972
     2973        /*
     2974         * Create the child process.
     2975         */
     2976        if (rc == 0)
     2977        {
     2978            HANDLE hProcess;
     2979            rc = mkWinChildcareWorkerCreateProcess(pWorker, pwszImageName, pwszCommandLine, pwszzEnvironment,
     2980                                                   pwszCwd, pafReplace, pahReplace, TRUE /*fCatchOutput*/, &hProcess);
     2981            if (rc == 0)
     2982            {
     2983                /*
     2984                 * Wait for the child to complete.
     2985                 */
     2986                rc = mkWinChildcareWorkerWaitForProcess(pWorker, pWorker->pCurChild, hProcess, pwszImageName,
     2987                                                        TRUE /*fCatchOutput*/);
     2988                CloseHandle(hProcess);
     2989            }
     2990        }
     2991    }
     2992
     2993    free(pwszCwd);
     2994    free(pwszCommandLine);
     2995    free(pwszImageName);
     2996    free(pwszzEnvironment);
     2997
     2998    return rc;
     2999}
     3000
    28233001#endif /* CONFIG_NEW_WIN_CHILDREN */
    28243002
  • trunk/src/kmk/w32/winchildren.h

    r3172 r3195  
    4141int     MkWinChildCreateSubmit(intptr_t hEvent, void *pvSubmitWorker, pid_t *pPid);
    4242int     MkWinChildCreateRedirect(intptr_t hProcess, pid_t *pPid);
     43# ifdef DECLARE_HANDLE
     44int     MkWinChildBuiltInExecChild(void *pvWorker, const char *pszExecutable, char **papszArgs, BOOL fQuotedArgv,
     45                                   char **papszEnvVars, const char *pszCwd, BOOL pafReplace[3], HANDLE pahReplace[3]);
     46# endif
    4347#endif
    4448int     MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild);
Note: See TracChangeset for help on using the changeset viewer.