VirtualBox

Changeset 3195 in kBuild for trunk/src/kmk/kmkbuiltin/redirect.c


Ignore:
Timestamp:
Mar 27, 2018 6: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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/redirect.c

    r3192 r3195  
    9292#  define LIBPATHSTRICT 3
    9393# endif
     94#endif
     95
     96#ifndef KMK_BUILTIN_STANDALONE
     97extern void kmk_cache_exec_image_a(const char *); /* imagecache.c */
    9498#endif
    9599
     
    596600
    597601/**
     602 * Registers the child process with a care provider or waits on it to complete.
     603 *
     604 * @returns 0 or non-zero success indicator or child exit code, depending on
     605 *          the value pfIsChildExitCode points to.
     606 * @param   pCtx                The command execution context.
     607 * @param   hProcess            The child process handle.
     608 * @param   cVerbosity          The verbosity level.
     609 * @param   pPidSpawned         Where to return the PID of the spawned child
     610 *                              when we're inside KMK and we're return without
     611 *                              waiting.
     612 * @param   pfIsChildExitCode   Where to indicate whether the return exit code
     613 *                              is from the child or from our setup efforts.
     614 */
     615static int kRedirectPostnatalCareOnWindows(PKMKBUILTINCTX pCtx, HANDLE hProcess, unsigned cVerbosity,
     616                                           pid_t *pPidSpawned, KBOOL *pfIsChildExitCode)
     617{
     618    int   rcExit;
     619    DWORD dwTmp;
     620
     621# ifndef KMK_BUILTIN_STANDALONE
     622    /*
     623     * Try register the child with a childcare provider, i.e. winchildren.c
     624     * or sub_proc.c.
     625     */
     626#  ifndef CONFIG_NEW_WIN_CHILDREN
     627    if (process_kmk_register_redirect(hProcess, pPidSpawned) == 0)
     628#  else
     629    if (   pPidSpawned
     630        && MkWinChildCreateRedirect((intptr_t)hProcess, pPidSpawned) == 0)
     631#  endif
     632    {
     633        if (cVerbosity > 0)
     634            warnx(pCtx, "debug: spawned %d", *pPidSpawned);
     635        *pfIsChildExitCode = K_FALSE;
     636        return 0;
     637    }
     638#  ifndef CONFIG_NEW_WIN_CHILDREN
     639    warn(pCtx, "sub_proc is out of slots, waiting for child...");
     640#  else
     641    if (pPidSpawned)
     642        warn(pCtx, "MkWinChildCreateRedirect failed...");
     643#  endif
     644# endif
     645
     646    /*
     647     * Either the provider is outbooked or we're not in a context (like
     648     * standalone) where we get help with waiting and must to it ourselves
     649     */
     650    dwTmp = WaitForSingleObject(hProcess, INFINITE);
     651    if (dwTmp != WAIT_OBJECT_0)
     652        warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp);
     653
     654    if (GetExitCodeProcess(hProcess, &dwTmp))
     655        rcExit = (int)dwTmp;
     656    else
     657    {
     658        warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError());
     659        TerminateProcess(hProcess, 127);
     660        rcExit = 127;
     661    }
     662
     663    CloseHandle(hProcess);
     664    *pfIsChildExitCode = K_TRUE;
     665    return rcExit;
     666}
     667
     668
     669/**
    598670 * Tries to locate the executable image.
    599671 *
     
    665737
    666738   return pszExecutable;
     739}
     740
     741
     742/**
     743 * Turns the orders into input for nt_child_inject_standard_handles and
     744 * winchildren.c
     745 *
     746 * @returns 0 on success, non-zero on failure.
     747 * @param   pCtx                The command execution context.
     748 * @param   cOrders             Number of file operation orders.
     749 * @param   paOrders            The file operation orders.
     750 * @param   pafReplace          Replace (TRUE) or leave alone (FALSE) indicator
     751 *                              for each of the starndard handles.
     752 * @param   pahChild            Array of standard handles for injecting into the
     753 *                              child.  Parallel to pafReplace.
     754 */
     755static int kRedirectOrderToWindowsHandles(PKMKBUILTINCTX pCtx, unsigned cOrders, REDIRECTORDERS *paOrders,
     756                                          BOOL pafReplace[3], HANDLE pahChild[3])
     757{
     758    int i;
     759    for (i = 0; i < (int)cOrders; i++)
     760    {
     761        int fdTarget = paOrders[i].fdTarget;
     762        assert(fdTarget >= 0 && fdTarget < 3);
     763        switch (paOrders[i].enmOrder)
     764        {
     765            case kRedirectOrder_Open:
     766                if (   (paOrders[i].fOpen & O_APPEND)
     767                    && lseek(paOrders[i].fdSource, 0, SEEK_END) < 0)
     768                    return err(pCtx, 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget);
     769                /* fall thru */
     770            case kRedirectOrder_Dup:
     771                pahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource);
     772                if (pahChild[fdTarget] == NULL || pahChild[fdTarget] == INVALID_HANDLE_VALUE)
     773                    return err(pCtx, 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget);
     774                break;
     775
     776            case kRedirectOrder_Close:
     777                pahChild[fdTarget] = NULL;
     778                break;
     779
     780            default:
     781                assert(0);
     782        }
     783        pafReplace[fdTarget] = TRUE;
     784    }
     785    return 0;
    667786}
    668787
     
    774893                CloseHandle(ProcInfo.hThread);
    775894                *phProcess = ProcInfo.hProcess;
     895# ifndef KMK_BUILTIN_STANDALONE
     896                kmk_cache_exec_image_a(pszExecutable);
     897# endif
    776898                rc = 0;
    777899            }
     
    789911            BOOL   afReplace[3] = { FALSE, FALSE, FALSE };
    790912            HANDLE ahChild[3]   = { NULL,  NULL,  NULL  };
    791             rc = 0;
    792             for (i = 0; i < (int)cOrders; i++)
    793             {
    794                 int fdTarget = paOrders[i].fdTarget;
    795                 assert(fdTarget >= 0 && fdTarget < 3);
    796                 switch (paOrders[i].enmOrder)
    797                 {
    798                     case kRedirectOrder_Open:
    799                         if (   (paOrders[i].fOpen & O_APPEND)
    800                             && lseek(paOrders[i].fdSource, 0, SEEK_END) < 0)
    801                             rc = err(pCtx, 10, "lseek-to-end failed on %d (for %d)", paOrders[i].fdSource, fdTarget);
    802                     case kRedirectOrder_Dup:
    803                         ahChild[fdTarget] = (HANDLE)_get_osfhandle(paOrders[i].fdSource);
    804                         if (ahChild[fdTarget] == NULL || ahChild[fdTarget] == INVALID_HANDLE_VALUE)
    805                             rc = err(pCtx, 10, "_get_osfhandle failed on %d (for %d)", paOrders[i].fdSource, fdTarget);
    806                         break;
    807                     case kRedirectOrder_Close:
    808                         ahChild[fdTarget] = NULL;
    809                         break;
    810                     default:
    811                         assert(0);
    812                 }
    813                 afReplace[fdTarget] = TRUE;
    814             }
     913            rc = kRedirectOrderToWindowsHandles(pCtx, cOrders, paOrders, afReplace, ahChild);
    815914            if (rc == 0)
    816915            {
     
    835934                    CloseHandle(ProcInfo.hThread);
    836935                    *phProcess = ProcInfo.hProcess;
     936# ifndef KMK_BUILTIN_STANDALONE
     937                    kmk_cache_exec_image_a(pszExecutable);
     938# endif
    837939                    rc = 0;
    838940                }
     
    848950    return rc;
    849951}
     952
     953# if !defined(KMK_BUILTIN_STANDALONE) && defined(CONFIG_NEW_WIN_CHILDREN)
     954/**
     955 * Pass the problem on to winchildren.c when we're on one of its workers.
     956 *
     957 * @returns 0 on success, non-zero on failure to create.
     958 * @param   pCtx                The command execution context.
     959 * @param   pszExecutable       The child process executable.
     960 * @param   cArgs               Number of arguments.
     961 * @param   papszArgs           The child argument vector.
     962 * @param   papszEnvVars        The child environment vector.
     963 * @param   pszCwd              The current working directory of the child.
     964 * @param   cOrders             Number of file operation orders.
     965 * @param   paOrders            The file operation orders.
     966 * @param   phProcess           Where to return process handle.
     967 * @param   pfIsChildExitCode   Where to indicate whether the return exit code
     968 *                              is from the child or from our setup efforts.
     969 */
     970static int kRedirectExecProcessWithinOnWorker(PKMKBUILTINCTX pCtx, const char *pszExecutable, int cArgs, char **papszArgs,
     971                                              char **papszEnvVars, const char *pszCwd, unsigned cOrders,
     972                                              REDIRECTORDERS *paOrders, KBOOL *pfIsChildExitCode)
     973{
     974    BOOL   afReplace[3] = { FALSE, FALSE, FALSE };
     975    HANDLE ahChild[3]   = { NULL,  NULL,  NULL  };
     976    int rc = kRedirectOrderToWindowsHandles(pCtx, cOrders, paOrders, afReplace, ahChild);
     977    if (rc == 0)
     978    {
     979        rc = MkWinChildBuiltInExecChild(pCtx->pvWorker, pszExecutable, papszArgs, TRUE /*fQuotedArgv*/,
     980                                        papszEnvVars, pszCwd, afReplace, ahChild);
     981        *pfIsChildExitCode = K_TRUE;
     982    }
     983    return rc;
     984}
     985# endif /* !KMK_BUILTIN_STANDALONE */
    850986
    851987#endif /* KBUILD_OS_WINDOWS */
     
    9641100# ifdef KBUILD_OS_WINDOWS
    9651101                /* Windows is slightly complicated due to handles and winchildren.c. */
    966                 HANDLE hProcess = INVALID_HANDLE_VALUE;
    967                 rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars,
    968                                                        pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess);
    969                 if (rcExit == 0)
    970                 {
    971 #  ifndef CONFIG_NEW_WIN_CHILDREN
    972                     if (process_kmk_register_redirect(hProcess, pPidSpawned) == 0)
    973 #  else
    974                     if (   pPidSpawned
    975                         && MkWinChildCreateRedirect((intptr_t)hProcess, pPidSpawned) == 0)
     1102                if (pPidSpawned)
     1103                    *pPidSpawned = 0;
     1104#  ifdef CONFIG_NEW_WIN_CHILDREN
     1105                if (pCtx->pvWorker && !pPidSpawned)
     1106                    rcExit = kRedirectExecProcessWithinOnWorker(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars,
     1107                                                                pszSavedCwd ? pszCwd : NULL, cOrders, paOrders,
     1108                                                                pfIsChildExitCode);
     1109                else
    9761110#  endif
    977                     {
    978                         if (cVerbosity > 0)
    979                             warnx(pCtx, "debug: spawned %d", *pPidSpawned);
    980                     }
    981                     else
    982                     {
    983                         DWORD dwTmp;
    984 #  ifndef CONFIG_NEW_WIN_CHILDREN
    985                         warn(pCtx, "sub_proc is out of slots, waiting for child...");
    986 #  else
    987                         if (pPidSpawned)
    988                             warn(pCtx, "MkWinChildCreateRedirect failed...");
    989 #  endif
    990                         dwTmp = WaitForSingleObject(hProcess, INFINITE);
    991                         if (dwTmp != WAIT_OBJECT_0)
    992                             warnx(pCtx, "WaitForSingleObject failed: %#x\n", dwTmp);
    993 
    994                         if (GetExitCodeProcess(hProcess, &dwTmp))
    995                             rcExit = (int)dwTmp;
    996                         else
    997                         {
    998                             warnx(pCtx, "GetExitCodeProcess failed: %u\n", GetLastError());
    999                             TerminateProcess(hProcess, 127);
    1000                             rcExit = 127;
    1001                         }
    1002 
    1003                         CloseHandle(hProcess);
    1004                         if (pPidSpawned)
    1005                             *pPidSpawned = 0;
    1006                         *pfIsChildExitCode = K_TRUE;
    1007                     }
     1111                {
     1112                    HANDLE hProcess = INVALID_HANDLE_VALUE;
     1113                    rcExit = kRedirectCreateProcessWindows(pCtx, pszExecutable, cArgs, papszArgs, papszEnvVars,
     1114                                                           pszSavedCwd ? pszCwd : NULL, cOrders, paOrders, &hProcess);
     1115                    if (rcExit == 0)
     1116                        rcExit = kRedirectPostnatalCareOnWindows(pCtx, hProcess, cVerbosity, pPidSpawned, pfIsChildExitCode);
    10081117                }
    10091118
     
    10521161                    dwWait = 11;
    10531162                    if (GetExitCodeProcess(hProcess, &dwWait))
     1163                    {
     1164                        *pfIsChildExitCode = K_TRUE;
    10541165                        rcExit = dwWait;
     1166                    }
    10551167                    else
    10561168                        rcExit = errx(pCtx, 11, "GetExitCodeProcess(%s) failed: %u", pszExecutable, GetLastError());
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette