Rather than waiting for IO to be possible, doesn't the sendfile() return the
number of bytes written? In other words, you would get EAGAIN *and* bytes
written. Thus, you know not to send that data again.
Seems like that would save a syscall for calls with timeout > 0.
Cheers,
-g
On Fri, Dec 22, 2000 at 12:19:17AM -0000, [EMAIL PROTECTED] wrote:
> rbb 00/12/21 16:19:17
>
> Modified: . CHANGES
> network_io/unix sendrecv.c
> Log:
> On FreeBSD, it is possible for the first call to sendfile to
> get EAGAIN, but still send some data. This means that we cannot
> call sendfile and then check for EAGAIN, and then wait and call
> sendfile again. If we do that, then we are likely to send the
> first chunk of data twice, once in the first call and once in the
> second. If we are using a timed write, then we check to make sure
> we can send data before trying to send it. This gets sendfile working
> on FreeBSD in Apache again.
>
> Revision Changes Path
> 1.30 +8 -0 apr/CHANGES
>
> Index: CHANGES
> ===================================================================
> RCS file: /home/cvs/apr/CHANGES,v
> retrieving revision 1.29
> retrieving revision 1.30
> diff -u -r1.29 -r1.30
> --- CHANGES 2000/12/22 00:02:49 1.29
> +++ CHANGES 2000/12/22 00:19:14 1.30
> @@ -1,5 +1,13 @@
> Changes with APR b1
>
> + *) On FreeBSD, it is possible for the first call to sendfile to
> + get EAGAIN, but still send some data. This means that we cannot
> + call sendfile and then check for EAGAIN, and then wait and call
> + sendfile again. If we do that, then we are likely to send the
> + first chunk of data twice, once in the first call and once in the
> + second. If we are using a timed write, then we check to make sure
> + we can send data before trying to send it. [Ryan Bloom]
> +
> *) Cleanup to help Apache support programs build cleanly.
> [Cliff Woolley <[EMAIL PROTECTED]>]
>
>
>
>
> 1.52 +15 -22 apr/network_io/unix/sendrecv.c
>
> Index: sendrecv.c
> ===================================================================
> RCS file: /home/cvs/apr/network_io/unix/sendrecv.c,v
> retrieving revision 1.51
> retrieving revision 1.52
> diff -u -r1.51 -r1.52
> --- sendrecv.c 2000/11/17 04:19:18 1.51
> +++ sendrecv.c 2000/12/22 00:19:16 1.52
> @@ -412,6 +412,21 @@
> headerstruct.trl_cnt = hdtr->numtrailers;
>
> /* FreeBSD can send the headers/footers as part of the system call */
> + if (sock->timeout > 0) {
> + /* On FreeBSD, it is possible for the first call to sendfile to
> + * get EAGAIN, but still send some data. This means that we cannot
> + * call sendfile and then check for EAGAIN, and then wait and call
> + * sendfile again. If we do that, then we are likely to send the
> + * first chunk of data twice, once in the first call and once in
> the
> + * second. If we are using a timed write, then we check to make
> sure
> + * we can send data before trying to send it.
> + */
> + apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + if (arv != APR_SUCCESS) {
> + *len = 0;
> + return arv;
> + }
> + }
>
> do {
> if (bytes_to_send) {
> @@ -442,28 +457,6 @@
> }
> }
> } while (rv == -1 && errno == EINTR);
> -
> - if (rv == -1 &&
> - (errno == EAGAIN || errno == EWOULDBLOCK) &&
> - sock->timeout > 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> - if (arv != APR_SUCCESS) {
> - *len = 0;
> - return arv;
> - }
> - else {
> - do {
> - rv = sendfile(file->filedes, /* open file descriptor of the
> file to be sent */
> - sock->socketdes, /* socket */
> - *offset, /* where in the file to start */
> - (size_t) * len, /* number of bytes to send */
> - &headerstruct, /* Headers/footers */
> - &nbytes, /* number of bytes written */
> - flags /* undefined, set to 0 */
> - );
> - } while (rv == -1 && errno == EINTR);
> - }
> - }
>
> (*len) = nbytes;
> if (rv == -1) {
>
>
>
--
Greg Stein, http://www.lyra.org/