"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...

Reply via email to