예제 #1
0
파일: cmd.c 프로젝트: embedthis/mpr
/*
    Windows only routine to wait for I/O on the channels to the gateway and the child process.
    This will queue events on the dispatcher queue when I/O occurs or the process dies.
    NOTE: NamedPipes cannot use WaitForMultipleEvents, so we dedicate a thread to polling.
    WARNING: this should not be called from a dispatcher other than cmd->dispatcher.
 */
static void pollWinCmd(MprCmd *cmd, MprTicks timeout)
{
    MprTicks        mark, delay;
    MprWaitHandler  *wp;
    int             i, rc, nbytes;

    mark = mprGetTicks();
    if (cmd->stopped) {
        timeout = 0;
    }
    slock(cmd);
    for (i = MPR_CMD_STDOUT; i < MPR_CMD_MAX_PIPE; i++) {
        if (cmd->files[i].handle) {
            wp = cmd->handlers[i];
            if (wp && wp->desiredMask & MPR_READABLE) {
                rc = PeekNamedPipe(cmd->files[i].handle, NULL, 0, NULL, &nbytes, NULL);
                if (rc && nbytes > 0 || cmd->process == 0) {
                    wp->presentMask |= MPR_READABLE;
                    mprQueueIOEvent(wp);
                }
            }
        }
    }
    if (cmd->files[MPR_CMD_STDIN].handle) {
        wp = cmd->handlers[MPR_CMD_STDIN];
        if (wp && wp->desiredMask & MPR_WRITABLE) {
            wp->presentMask |= MPR_WRITABLE;
            mprQueueIOEvent(wp);
        }
    }
    if (cmd->process) {
        delay = (cmd->eofCount == cmd->requiredEof && cmd->files[MPR_CMD_STDIN].handle == 0) ? timeout : 0;
        do {
            mprYield(MPR_YIELD_STICKY);
            if (WaitForSingleObject(cmd->process, (DWORD) delay) == WAIT_OBJECT_0) {
                mprResetYield();
                reapCmd(cmd, 0);
                break;
            } else {
                mprResetYield();
            }
            delay = mprGetRemainingTicks(mark, timeout);
        } while (cmd->eofCount == cmd->requiredEof);
    }
    sunlock(cmd);
}
예제 #2
0
static void serviceIO(MprWaitService *ws, struct epoll_event *events, int count)
{
    MprWaitHandler      *wp;
    struct epoll_event  *ev;
    int                 fd, i, mask;

    lock(ws);
    for (i = 0; i < count; i++) {
        ev = &events[i];
        fd = ev->data.fd;
        if (fd == ws->breakFd[MPR_READ_PIPE]) {
            char buf[16];
            if (read(fd, buf, sizeof(buf)) < 0) {}
            continue;
        }
        if (fd < 0 || (wp = mprGetItem(ws->handlerMap, fd)) == 0) {
            /*
                This can happen if a writable event has been triggered (e.g. MprCmd command stdin pipe) and the pipe is closed.
                This thread may have waked from kevent before the pipe is closed and the wait handler removed from the map.

                mprLog("error mpr event", 0, "fd not in handler map. fd %d", fd);
             */
            continue;
        }
        mask = 0;
        if (ev->events & (EPOLLIN | EPOLLHUP | EPOLLERR)) {
            mask |= MPR_READABLE;
        }
        if (ev->events & (EPOLLOUT | EPOLLHUP)) {
            mask |= MPR_WRITABLE;
        }
        wp->presentMask = mask & wp->desiredMask;
        if (wp->presentMask) {
            if (wp->flags & MPR_WAIT_IMMEDIATE) {
                (wp->proc)(wp->handlerData, NULL);
            } else {
                /*
                    Suppress further events while this event is being serviced. User must re-enable.
                 */
                mprNotifyOn(wp, 0);
                mprQueueIOEvent(wp);
            }
        }
    }
    unlock(ws);
}
예제 #3
0
파일: wait.c 프로젝트: embedthis/mpr
/*
    Recall a handler which may have buffered data. Only called by notifiers.
 */
PUBLIC void mprDoWaitRecall(MprWaitService *ws)
{
    MprWaitHandler      *wp;
    int                 index;

    if (!ws) {
        return;
    }
    lock(ws);
    ws->needRecall = 0;
    for (index = 0; (wp = (MprWaitHandler*) mprGetNextItem(ws->handlers, &index)) != 0; ) {
        if ((wp->flags & MPR_WAIT_RECALL_HANDLER) && (wp->desiredMask & MPR_READABLE)) {
            wp->presentMask |= MPR_READABLE;
            wp->flags &= ~MPR_WAIT_RECALL_HANDLER;
            mprNotifyOn(wp, 0);
            mprQueueIOEvent(wp);
        }
    }
    unlock(ws);
}
예제 #4
0
파일: async.c 프로젝트: sunfirefox/mpr-4
PUBLIC void mprServiceWinIO(MprWaitService *ws, int sockFd, int winMask)
{
    MprWaitHandler      *wp;
    int                 index;

    lock(ws);

    for (index = 0; (wp = (MprWaitHandler*) mprGetNextItem(ws->handlers, &index)) != 0; ) {
        if (wp->fd == sockFd) {
            break;
        }
    }
    if (wp == 0) {
        /* If the server forcibly closed the socket, we may still get a read event. Just ignore it.  */
        unlock(ws);
        return;
    }
    /*
        Mask values: READ==1, WRITE=2, ACCEPT=8, CONNECT=10, CLOSE=20
     */
    wp->presentMask = 0;
    if (winMask & (FD_READ | FD_ACCEPT | FD_CLOSE)) {
        wp->presentMask |= MPR_READABLE;
    }
    if (winMask & (FD_WRITE | FD_CONNECT)) {
        wp->presentMask |= MPR_WRITABLE;
    }
    wp->presentMask &= wp->desiredMask;
    if (wp->presentMask) {
        if (wp->flags & MPR_WAIT_IMMEDIATE) {
            (wp->proc)(wp->handlerData, NULL);
        } else {
            mprNotifyOn(ws, wp, 0);
            mprQueueIOEvent(wp);
        }
    }
    unlock(ws);
}