in modules/fcgid/fcgid_proc_unix.c [631:713]
static apr_status_t socket_writev(fcgid_ipc *ipc_handle,
struct iovec *vec, int nvec,
int *writecnt)
{
apr_status_t rv;
int retcode, unix_socket;
fcgid_namedpipe_handle *handle_info;
struct pollfd pollfds[1];
handle_info = (fcgid_namedpipe_handle *) ipc_handle->ipc_handle_info;
unix_socket = handle_info->handle_socket;
/* Try nonblock write */
do {
if ((retcode = writev(unix_socket, vec, nvec)) > 0) {
*writecnt = retcode;
return APR_SUCCESS;
}
} while (retcode == -1 && APR_STATUS_IS_EINTR(errno));
rv = errno;
if (APR_STATUS_IS_EAGAIN(rv)) {
/* poll() */
pollfds[0].fd = unix_socket;
pollfds[0].events = POLLOUT;
do {
retcode = poll(pollfds, 1, ipc_handle->communation_timeout * 1000);
} while (retcode < 0 && APR_STATUS_IS_EINTR(errno));
if (retcode < 0) {
rv = errno;
}
else if (retcode == 0) {
rv = APR_TIMEUP;
}
else {
/* Write again */
do {
if ((retcode = writev(unix_socket, vec, nvec)) > 0) {
*writecnt = retcode;
return APR_SUCCESS;
}
} while (retcode == -1 && APR_STATUS_IS_EINTR(errno));
rv = errno;
}
}
if (APR_STATUS_IS_EAGAIN(rv)) {
/* socket is writable, but we can't write the entire buffer; try to write a
* smaller amount, and if even that fails then sleep
*/
size_t to_write = vec[0].iov_len;
int slept = 0;
const apr_interval_time_t sleep_time = APR_USEC_PER_SEC / 4;
const int max_sleeps = 8;
do {
if ((retcode = write(unix_socket, vec[0].iov_base, to_write)) > 0) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ipc_handle->request,
"wrote %d byte(s) and slept %d time(s) after EAGAIN",
retcode, slept);
*writecnt = retcode;
return APR_SUCCESS;
}
if (APR_STATUS_IS_EAGAIN(errno)) {
if (to_write == 1) {
apr_sleep(sleep_time);
++slept;
}
else {
to_write /= 2;
}
}
} while ((APR_STATUS_IS_EINTR(errno) || APR_STATUS_IS_EAGAIN(errno))
&& slept < max_sleeps);
rv = errno;
}
ap_log_rerror(APLOG_MARK, APLOG_INFO, rv,
ipc_handle->request,
"mod_fcgid: error writing data to FastCGI server");
return rv;
}