"Takashima, Makoto" <[EMAIL PROTECTED]> writes: > 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()
FYI... this discussion belongs on [EMAIL PROTECTED] the srclib/apr tree in the httpd-2.0 directory are a copy of the APR project code... > It seems assuming write request never fail when > apr_wait_for_io_or_timeout() succeeded, but it is not true > for pipe. ... > - 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]. ... boy, this sucks :) no syscall to block until timeout occurs or we can write the whole message... note that most existing users of APR pipes don't care about atomic writes... I wonder if it is appropriate to have a pipe setting that says that atomic is important... if really important, I guess we'd have to sleep before retry... otherwise maybe we should try to write a smaller amount to the pipe... it would be a shame to waste our timeslice, which could cause the reader to have to block too once the other side is empty... > 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] > -- Jeff Trawick | [EMAIL PROTECTED] Born in Roswell... married an alien...