/* * Poll for I/O events on the CGI pipes */ void mprPollCmdPipes(MprCmd *cmd, int timeout) { #if BLD_WIN_LIKE && !WINCE if (cmd->files[MPR_CMD_STDOUT].handle) { if (serviceCmdEvents(cmd, MPR_CMD_STDOUT, timeout) > 0 && (cmd->flags & MPR_CMD_OUT)) { stdoutCallback(cmd, MPR_READABLE); } } else if (cmd->files[MPR_CMD_STDERR].handle) { if (serviceCmdEvents(cmd, MPR_CMD_STDERR, timeout) > 0 && (cmd->flags & MPR_CMD_ERR)) { stderrCallback(cmd, MPR_READABLE); } } #else if (cmd->files[MPR_CMD_STDOUT].fd >= 0) { if (mprWaitForSingleIO(cmd, cmd->files[MPR_CMD_STDOUT].fd, MPR_READABLE, timeout)) { stdoutCallback(cmd, MPR_READABLE); } } else if (cmd->files[MPR_CMD_STDERR].fd >= 0) { if (mprWaitForSingleIO(cmd, cmd->files[MPR_CMD_STDERR].fd, MPR_READABLE, timeout)) { stderrCallback(cmd, MPR_READABLE); } } #endif }
/* Write a block of data. This is the lowest level write routine for data. This will buffer the data and flush if the queue buffer is full. Flushing is done by calling httpFlushQueue which will service queues as required. This may call the queue outgoing service routine and disable downstream queues if they are overfull. This routine will always accept the data and never return "short". */ PUBLIC ssize httpWriteBlock(HttpQueue *q, cchar *buf, ssize len, int flags) { HttpPacket *packet; HttpConn *conn; HttpTx *tx; ssize totalWritten, packetSize, thisWrite; assert(q == q->conn->writeq); conn = q->conn; tx = conn->tx; if (flags == 0) { flags = HTTP_BUFFER; } if (tx == 0 || tx->finalizedOutput) { return MPR_ERR_CANT_WRITE; } tx->responded = 1; for (totalWritten = 0; len > 0; ) { mprTrace(7, "httpWriteBlock q_count %d, q_max %d", q->count, q->max); if (conn->state >= HTTP_STATE_FINALIZED) { return MPR_ERR_CANT_WRITE; } if (q->last && q->last != q->first && q->last->flags & HTTP_PACKET_DATA && mprGetBufSpace(q->last->content) > 0) { packet = q->last; } else { packetSize = (tx->chunkSize > 0) ? tx->chunkSize : q->packetSize; if ((packet = httpCreateDataPacket(packetSize)) == 0) { return MPR_ERR_MEMORY; } httpPutForService(q, packet, HTTP_DELAY_SERVICE); } assert(mprGetBufSpace(packet->content) > 0); thisWrite = min(len, mprGetBufSpace(packet->content)); if (flags & (HTTP_BLOCK | HTTP_NON_BLOCK)) { thisWrite = min(thisWrite, q->max - q->count); } if (thisWrite > 0) { if ((thisWrite = mprPutBlockToBuf(packet->content, buf, thisWrite)) == 0) { return MPR_ERR_MEMORY; } buf += thisWrite; len -= thisWrite; q->count += thisWrite; totalWritten += thisWrite; } if (q->count >= q->max) { httpFlushQueue(q, 0); if (q->count >= q->max) { if (flags & HTTP_NON_BLOCK) { break; } else if (flags & HTTP_BLOCK) { while (q->count >= q->max && !tx->finalized) { if (!mprWaitForSingleIO((int) conn->sock->fd, MPR_WRITABLE, conn->limits->inactivityTimeout)) { return MPR_ERR_TIMEOUT; } httpResumeQueue(conn->connectorq); httpServiceQueues(conn); } } } } } if (conn->error) { return MPR_ERR_CANT_WRITE; } return totalWritten; }