Exemple #1
0
/*
 *  Service I/O and return a count of characters that can be read without blocking. If the proces has completed,
 *  then return 1 to indicate that read can be called.
 */
static int serviceCmdEvents(MprCmd *cmd, int channel, int timeout)
{
    int     rc, count, status;

    if (mprGetDebugMode(cmd)) {
        timeout = MAXINT;
    }
    if (cmd->files[channel].handle) {
        rc = PeekNamedPipe(cmd->files[channel].handle, NULL, 0, NULL, &count, NULL);
        if (rc && count > 0) {
            return count;
        }
    }
    if (cmd->process == 0) {
        return 1;
    }
    if ((status = WaitForSingleObject(cmd->process, timeout)) == WAIT_OBJECT_0) {
        if (cmd->requiredEof == 0) {
            mprReapCmd(cmd, MPR_TIMEOUT_STOP_TASK);
            mprSignalCond(cmd->completeCond);
            return 0;
        }
        return 1;
    }
    return 0;
}
Exemple #2
0
/*
 *  Close a command channel. Must be able to be called redundantly.
 */
void mprCloseCmdFd(MprCmd *cmd, int channel)
{
    mprAssert(0 <= channel && channel <= MPR_CMD_MAX_PIPE);

    /*
     *  Disconnect but don't free. This prevents some races with callbacks.
     */
    if (cmd->handlers[channel]) {
        mprDisconnectWaitHandler(cmd->handlers[channel]);
    }

    if (cmd->files[channel].fd != -1) {
        close(cmd->files[channel].fd);
        cmd->files[channel].fd = -1;
#if BLD_WIN_LIKE
        cmd->files[channel].handle = 0;
#endif
        if (channel != MPR_CMD_STDIN) {
            if (++cmd->eofCount >= cmd->requiredEof) {
                mprReapCmd(cmd, MPR_TIMEOUT_STOP_TASK);
                mprSignalCond(cmd->completeCond);
            }
        }
    }
}
Exemple #3
0
static void resetCmd(MprCmd *cmd)
{
    MprCmdFile      *files;
    int             i;

    files = cmd->files;
    for (i = 0; i < MPR_CMD_MAX_PIPE; i++) {
        if (cmd->handlers[i]) {
            mprFree(cmd->handlers[i]);
            cmd->handlers[i] = 0;
        }
        if (files[i].clientFd >= 0) {
            close(files[i].clientFd);
            files[i].clientFd = -1;
        }
        if (files[i].fd >= 0) {
            close(files[i].fd);
            files[i].fd = -1;
        }
    }
    cmd->eofCount = 0;
    cmd->status = -1;
    mprResetCond(cmd->completeCond);

    if (cmd->pid && !(cmd->flags & MPR_CMD_DETACH)) {
        mprStopCmd(cmd);
        mprReapCmd(cmd, 0);
        mprSignalCond(cmd->completeCond);
    }
}
Exemple #4
0
int mprGetCmdExitStatus(MprCmd *cmd, int *statusp)
{
    mprAssert(statusp);

    if (cmd->pid) {
        mprReapCmd(cmd, MPR_TIMEOUT_STOP_TASK);
        if (cmd->pid) {
            return MPR_ERR_NOT_READY;
        }
    }
    *statusp = cmd->status;
    return 0;
}
Exemple #5
0
/*
 *  Wait for a command to complete. Return 0 if the command completed, otherwise return MPR_ERR_TIMEOUT. 
 *  This will call mprReapCmd if requried.
 */
int mprWaitForCmd(MprCmd *cmd, int timeout)
{
    MprTime     mark;
    int         complete, rc;

    if (timeout < 0) timeout = MAXINT;
    if (mprGetDebugMode(cmd)) timeout = MAXINT;

    mark = mprGetTime(cmd);
    complete = 0;

    do {
        if (cmd->requiredEof == 0) {
            if (mprReapCmd(cmd, 10) == 0) {
                mprSignalCond(cmd->completeCond);
                return 0;
            }
        }
        mprPollCmdPipes(cmd, timeout);
        rc = mprWaitForCondWithService(cmd->completeCond, 10);
        if (rc == 0) {
            complete++;
            break;
        } else if (rc != MPR_ERR_TIMEOUT) {
            mprAssert(0);
        }
    } while (mprGetElapsedTime(cmd, mark) <= timeout);

    if (!complete) {
        mprLog(cmd, 7, "cmd: mprWaitForCmd: timeout waiting for command to complete");
        return MPR_ERR_TIMEOUT;
    }
    if (cmd->pid) {
        mprReapCmd(cmd, MPR_TIMEOUT_STOP_TASK);
    }
    mprLog(cmd, 7, "cmd: waitForChild: status %d", cmd->status);
    return 0;
}
Exemple #6
0
/*
    This routine runs after all incoming data has been received
 */
static void runCgi(MaQueue *q)
{
    MaResponse  *resp;
    MaConn      *conn;
    MprCmd      *cmd;

    conn = q->conn;
    resp = conn->response;
    cmd = (MprCmd*) q->queueData;

    if (cmd == 0) {
        startCgi(q);
        cmd = (MprCmd*) q->queueData;
        if (q->pair->count > 0) {
            writeToCGI(q->pair);
        }
    }

    /*
        Close the CGI program's stdin. This will allow it to exit if it was expecting input data.
     */
    mprCloseCmdFd(cmd, MPR_CMD_STDIN);

    if (conn->requestFailed) {
        maPutForService(q, maCreateEndPacket(q), 1);
        return;
    }
    while (mprWaitForCmd(cmd, 1000) < 0) {
        if (mprGetElapsedTime(cmd, cmd->lastActivity) >= conn->host->timeout) {
            break;
        }
    }
    if (cmd->pid == 0) {
        maPutForService(q, maCreateEndPacket(q), 1);
    } else {
        mprStopCmd(cmd);
        mprReapCmd(cmd, MPR_TIMEOUT_STOP_TASK);
        cmd->status = 255;
    }
}