Ugh. Kudos to Greg for getting me to look at a truss/strace of httpd,
but I didn't find anything good to report...
On FreeBSD, it turns out we are being quite wasteful. It seems in all
cases when we are writing to the client, our socket is always
non-blocking, and therefore sendfile returns EAGAIN:
sendfile(0xf,0xe,0x0,0x0,0xedb4,0xbfbfc5b0,0xbfbfc5a8,0x0) ERR#35
'Resource temporarily unavailable'
poll({14 0x0|IN|PRI|ERR|HUP|NVAL|RDNORM|RDBAND|WRBAND },1,300000) = 1 (0x1)
sendfile(0xf,0xe,0x8000,0x0,0x6db4,0xbfbfc5b0,0xbfbfc5a8,0x0) ERR#35
'Resource temporarily unavailable'
poll({14 0x0|IN|PRI|ERR|HUP|NVAL|RDNORM|RDBAND|WRBAND },1,300000) = 1 (0x1)
sendfile(0xf,0xe,0x9000,0x0,0x5db4,0xbfbfc5b0,0xbfbfc5a8,0x0) ERR#35
'Resource temporarily unavailable'
poll({14 0x0|IN|PRI|ERR|HUP|NVAL|RDNORM|RDBAND|WRBAND },1,300000) = 1 (0x1)
sendfile(0xf,0xe,0xa000,0x0,0x4db4,0xbfbfc5b0,0xbfbfc5a8,0x0) ERR#35
'Resource temporarily unavailable'
poll({14 0x0|IN|PRI|ERR|HUP|NVAL|RDNORM|RDBAND|WRBAND },1,300000) = 1 (0x1)
sendfile(0xf,0xe,0xb000,0x0,0x3db4,0xbfbfc5b0,0xbfbfc5a8,0x0) ERR#35
'Resource temporarily unavailable'
poll({14 0x0|IN|PRI|ERR|HUP|NVAL|RDNORM|RDBAND|WRBAND },1,300000) = 1 (0x1)
sendfile(0xf,0xe,0xc000,0x0,0x2db4,0xbfbfc5b0,0xbfbfc5a8,0x0) ERR#35
'Resource temporarily unavailable'
poll({14 0x0|IN|PRI|ERR|HUP|NVAL|RDNORM|RDBAND|WRBAND },1,300000) = 1 (0x1)
sendfile(0xf,0xe,0xd000,0x0,0x1db4,0xbfbfc5b0,0xbfbfc5a8,0x0) ERR#35
'Resource temporarily unavailable'
poll({14 0x0|IN|PRI|ERR|HUP|NVAL|RDNORM|RDBAND|WRBAND },1,300000) = 1 (0x1)
sendfile(0xf,0xe,0xe000,0x0,0xdb4,0xbfbfc5b0,0xbfbfc5a8,0x0) = 0 (0x0)
read(0xe,0x8173028,0x1f40) ERR#35 'Resource
temporarily unavailable'
write(8,0x81730f0,77) = 77 (0x4d)
close(15) = 0 (0x0)
8 calls to sendfile and poll to send a single 55K file. Ick.
I thought we were always supposed to be using a blocking socket when
doing the sendfile?
Index: core_filters.c
===================================================================
--- core_filters.c (revision 201576)
+++ core_filters.c (working copy)
@@ -845,6 +845,8 @@
return APR_SUCCESS;
}
+ apr_socket_opt_set(net->client_socket, APR_SO_NONBLOCK, 0);
+
if (fd) {
apr_hdtr_t hdtr;
apr_size_t bytes_sent;
After adding this patch, truss looks like:
fcntl(14,F_GETFL,0x10) = 6 (0x6)
fcntl(14,F_SETFL,0x2) = 0 (0x0)
sendfile(0xf,0xe,0x0,0x0,0xedb4,0xbfbfc5b0,0xbfbfc5a8,0x0) = 0 (0x0)
read(0xe,0x8173028,0x1f40) = 355 (0x163)
write(8,0x81750f0,77) = 77 (0x4d)
close(15) = 0 (0x0)
Is our code for detection of inheriting non-blocking from the listening
socket broken?
-Paul