apr_status_t proc_write_ipc()

in modules/fcgid/fcgid_proc_win.c [376:461]


apr_status_t proc_write_ipc(fcgid_ipc * ipc_handle,
                            apr_bucket_brigade * birgade_send)
{
    fcgid_namedpipe_handle *handle_info;
    apr_bucket *bucket_request;
    apr_status_t rv;
    DWORD transferred;
    apr_bucket_brigade *tmpbb = apr_brigade_create(birgade_send->p, 
                                                   birgade_send->bucket_alloc);

    handle_info = (fcgid_namedpipe_handle *) ipc_handle->ipc_handle_info;

    while (!APR_BRIGADE_EMPTY(birgade_send)) {
        const char *write_buf;
        apr_size_t write_buf_len;
        apr_size_t has_write;

        bucket_request = APR_BRIGADE_FIRST(birgade_send);

        if (APR_BUCKET_IS_METADATA(bucket_request)) {
            apr_bucket_delete(bucket_request);
            continue;
        }

        if ((rv = apr_bucket_read(bucket_request, &write_buf, &write_buf_len,
                                  APR_BLOCK_READ)) != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, ipc_handle->request,
                          "mod_fcgid: can't read request from bucket");
            return rv;
        }

        APR_BUCKET_REMOVE(bucket_request);
        APR_BRIGADE_INSERT_TAIL(tmpbb, bucket_request);

        /* Write the buffer to fastcgi server */
        has_write = 0;
        while (has_write < write_buf_len) {
            DWORD byteswrite;

            if (WriteFile(handle_info->handle_pipe,
                          write_buf + has_write,
                          write_buf_len - has_write,
                          &byteswrite, &handle_info->overlap_write)) {
                has_write += byteswrite;
                apr_brigade_cleanup(tmpbb);
                continue;
            } else if ((rv = GetLastError()) != ERROR_IO_PENDING) {
                ap_log_rerror(APLOG_MARK, APLOG_WARNING,
                              APR_FROM_OS_ERROR(rv), ipc_handle->request,
                              "mod_fcgid: can't write to pipe");
                return rv;
            } else {
                /*
                   it's ERROR_IO_PENDING on write
                 */
                DWORD dwWaitResult =
                    WaitForSingleObject(handle_info->overlap_write.hEvent,
                                        ipc_handle->communation_timeout * 1000);
                if (dwWaitResult == WAIT_OBJECT_0) {
                    if (!GetOverlappedResult(handle_info->handle_pipe,
                                             &handle_info->overlap_write,
                                             &transferred,
                                             FALSE /* don't wait */ )
                        || transferred == 0)
                    {
                        ap_log_rerror(APLOG_MARK, APLOG_WARNING,
                                      apr_get_os_error(), ipc_handle->request,
                                      "mod_fcgid: get overlap result error");
                        return APR_ESPIPE;
                    }
                    has_write += transferred;
                    apr_brigade_cleanup(tmpbb);
                    continue;
                } else {
                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
                                  ipc_handle->request,
                                  "mod_fcgid: write timeout to pipe");
                    return APR_ESPIPE;
                }
            }
        }
    }

    apr_brigade_destroy(tmpbb);
    return APR_SUCCESS;
}