Ignore:
Timestamp:
Feb 28, 2009, 8:25:12 AM (16 years ago)
Author:
bird
Message:

kash: forking on windows (almost there).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kash/shinstance.c

    r2292 r2293  
    3838# include <pwd.h>
    3939#endif
     40#if K_OS == K_OS_WINDOWS
     41# include <Windows.h>
     42#endif
    4043#include "shinstance.h"
    4144
    4245#if K_OS == K_OS_WINDOWS
    43 extern pid_t shfork_do_it(void); /* shforkA-win.asm */
     46extern pid_t shfork_do_it(shinstance *psh); /* shforkA-win.asm */
    4447#endif
    4548
     
    308311}
    309312
     313/** getenv() */
    310314char *sh_getenv(shinstance *psh, const char *var)
    311315{
     
    868872}
    869873
     874/**
     875 * Adds a child to the shell
     876 *
     877 * @returns 0 on success, on failure -1 and errno set to ENOMEM.
     878 *
     879 * @param   psh     The shell instance.
     880 * @param   pid     The child pid.
     881 * @param   hChild  Windows child handle.
     882 */
     883int sh_add_child(shinstance *psh, pid_t pid, void *hChild)
     884{
     885    /* get a free table entry. */
     886    int i = psh->num_children++;
     887    if (!(i % 32))
     888    {
     889        void *ptr = sh_realloc(psh, psh->children, sizeof(*psh->children) * (i + 32));
     890        if (!ptr)
     891        {
     892            psh->num_children--;
     893            errno = ENOMEM;
     894            return -1;
     895        }
     896        psh->children = ptr;
     897    }
     898
     899    /* add it */
     900    psh->children[i].pid = pid;
     901#if K_OS == K_OS_WINDOWS
     902    psh->children[i].hChild = hChild;
     903#endif
     904    (void)hChild;
     905    return 0;
     906}
     907
    870908pid_t sh_fork(shinstance *psh)
    871909{
     
    877915
    878916#elif K_OS == K_OS_WINDOWS //&& defined(SH_FORKED_MODE)
    879     pid = shfork_do_it();
     917    pid = shfork_do_it(psh);
    880918
    881919#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
     
    896934}
    897935
     936/** waitpid() */
    898937pid_t sh_waitpid(shinstance *psh, pid_t pid, int *statusp, int flags)
    899938{
    900939    pid_t pidret;
    901 
     940#ifdef SH_PURE_STUB_MODE
    902941    *statusp = 0;
    903 #ifdef SH_PURE_STUB_MODE
    904942    pidret = -1;
    905943
    906 #elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
     944#elif K_OS == K_OS_WINDOWS //&& defined(SH_FORKED_MODE)
     945    DWORD   dwRet;
     946    HANDLE  hChild = INVALID_HANDLE_VALUE;
     947    int     i;
     948
     949    *statusp = 0;
     950    pidret = -1;
     951    if (pid != -1)
     952    {
     953        /*
     954         * A specific child, try look it up in the child process table
     955         * and wait for it.
     956         */
     957        for (i = 0; i < psh->num_children; i++)
     958            if (psh->children[i].pid == pid)
     959                break;
     960        if (i < psh->num_children)
     961        {
     962            dwRet = WaitForSingleObject(psh->children[i].hChild,
     963                                        flags & WNOHANG ? 0 : INFINITE);
     964            if (dwRet == WAIT_OBJECT_0)
     965                hChild = psh->children[i].hChild;
     966            else if (dwRet == WAIT_TIMEOUT)
     967            {
     968                i = -1; /* don't try close anything */
     969                pidret = 0;
     970            }
     971            else
     972                errno = ECHILD;
     973        }
     974        else
     975            errno = ECHILD;
     976    }
     977    else if (psh->num_children <= MAXIMUM_WAIT_OBJECTS)
     978    {
     979        HANDLE ahChildren[64];
     980        for (i = 0; i < psh->num_children; i++)
     981            ahChildren[i] = psh->children[i].hChild;
     982        dwRet = WaitForMultipleObjects(psh->num_children, &ahChildren[0],
     983                                       FALSE,
     984                                       flags & WNOHANG ? 0 : INFINITE);
     985        i = dwRet - WAIT_OBJECT_0;
     986        if ((unsigned)i < (unsigned)psh->num_children)
     987        {
     988            hChild = psh->children[i].hChild;
     989        }
     990        else if (dwRet == WAIT_TIMEOUT)
     991        {
     992            i = -1; /* don't try close anything */
     993            pidret = 0;
     994        }
     995        else
     996        {
     997            i = -1; /* don't try close anything */
     998            errno = EINVAL;
     999        }
     1000    }
     1001    else
     1002    {
     1003        fprintf(stderr, "panic! too many children!\n");
     1004        i = -1;
     1005        *(char *)1 = '\0'; /** @todo implement this! */
     1006    }
     1007
     1008    /*
     1009     * Close the handle, and if we succeeded collect the exit code first.
     1010     */
     1011    if (    i >= 0
     1012        &&  i < psh->num_children)
     1013    {
     1014        if (hChild != INVALID_HANDLE_VALUE)
     1015        {
     1016            DWORD dwExitCode = 127;
     1017            if (GetExitCodeProcess(hChild, &dwExitCode))
     1018            {
     1019                pidret = psh->children[i].pid;
     1020                if (dwExitCode && !W_EXITCODE(dwExitCode, 0))
     1021                    dwExitCode |= 16;
     1022                *statusp = W_EXITCODE(dwExitCode, 0);
     1023            }
     1024            else
     1025                errno = EINVAL;
     1026        }
     1027
     1028        /* remove and close */
     1029        hChild = psh->children[i].hChild;
     1030        psh->num_children--;
     1031        if (i < psh->num_children)
     1032            psh->children[i] = psh->children[psh->num_children];
     1033        i = CloseHandle(hChild); assert(i);
     1034    }
     1035
     1036#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
     1037    *statusp = 0;
    9071038# ifdef _MSC_VER
    9081039    pidret = -1;
Note: See TracChangeset for help on using the changeset viewer.