Hi, I found a problem with non-blocking write to pipe.
Current code (2.0.43) is as following. ------------------------------------------------------------ httpd-2.0.43/srclib/apr/file_io/unix/readwrite.c:apr_file_write() ------------------------------------------------------------ do { rv = write(thefile->filedes, buf, *nbytes); } while (rv == (apr_size_t)-1 && errno == EINTR); #ifdef USE_WAIT_FOR_IO if (rv == (apr_size_t)-1 && (errno == EAGAIN || errno == EWOULDBLOCK) && thefile->timeout != 0) { apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 0); if (arv != APR_SUCCESS) { *nbytes = 0; return arv; } else { do { rv = write(thefile->filedes, buf, *nbytes); } while (rv == (apr_size_t)-1 && errno == EINTR); } } #endif ------------------------------------------------------------ It seems assuming write request never fail when apr_wait_for_io_or_timeout() succeeded, but it is not true for pipe. "The Single UNIXR Specification, Version 2" is saying : ------------------------------------------------------------ Write requests to a pipe or FIFO will be handled the same as a regular file with the following exceptions: [snip] If the O_NONBLOCK flag is set, write() requests will be handled differently, in the following ways: - The write() function will not block the thread. - A write request for {PIPE_BUF} or fewer bytes will have the following effect: If there is sufficient space available in the pipe, write() will transfer all the data and return the number of bytes requested. Otherwise, write() will transfer no data and return -1 with errno set to [EAGAIN]. ------------------------------------------------------------ It means that if room on the pipe is smaller than *nbyes and *nbytes is less than or equal to {PIPE_BUF}, write() can fail with errno=EAGAIN and return -1, and apr_file_write() just fails. I found this problem on HP-UX11.0 whose PIPE_BUF is 8192 with CGI that receive more than 8kbytes POST request. This problem can be fixed with the following code, however I do not know if there is better solution other than looping. ------------------------------------------------------------ do { rv = write(thefile->filedes, buf, *nbytes); } while (rv == (apr_size_t)-1 && errno == EINTR); #ifdef USE_WAIT_FOR_IO if (rv == (apr_size_t)-1 && (errno == EAGAIN || errno == EWOULDBLOCK) && thefile->timeout != 0) { apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 0); if (arv != APR_SUCCESS) { *nbytes = 0; return arv; } else { do { rv = write(thefile->filedes, buf, *nbytes); /* write request of {PIPE_BUF} bytes or less may fail */ /* because it is atomic when writing to pipe or FIFO */ while (rv == (apr_size_t)-1 && *nbytes < PIPE_BUF && errno == EAGAIN) { apr_sleep(10000); /* sleep ~10ms */ rv = write(thefile->filedes, buf, *nbytes); } } while (rv == (apr_size_t)-1 && errno == EINTR); } } #endif ------------------------------------------------------------ -- [EMAIL PROTECTED]