This patch add support for write timeouts.
The patch also exist for squid3.1 branch
The development sponsored by the Measurement Factory
Description:
The write I/O timeout should trigger if Squid has data to write but
the connection is not ready to accept more data for the specified time.
If the write times out, the Comm caller's write handler is called with
an ETIMEDOUT COMM_ERROR error.
Comm may process a single write request in several chunks, without
caller's knowledge. The waiting time is reset internally by Comm after
each chunk is written.
Default timeout value is 15 minutes.
The implementation requires no changes in Comm callers but it adds write
timeouts to all connections, including the connections that have
context-specific write timeouts. I think that is fine.
-
Christos
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2009-11-29 05:33:51 +0000
+++ src/cf.data.pre 2009-12-15 18:17:23 +0000
@@ -3934,6 +3934,21 @@
default is 15 minutes.
DOC_END
+NAME: write_timeout
+COMMENT: time-units
+TYPE: time_t
+LOC: Config.Timeout.write
+DEFAULT: 15 minutes
+DOC_START
+ This timeout is tracked for all connections that have data
+ available for writing and are waiting for the socket to become
+ ready. After each successful write, the timeout is extended by
+ the configured amount. If Squid has data to write but the
+ connection is not ready for the configured duration, the
+ transaction associated with the connection is terminated. The
+ default is 15 minutes.
+DOC_END
+
NAME: request_timeout
TYPE: time_t
LOC: Config.Timeout.request
=== modified file 'src/comm.cc'
--- src/comm.cc 2009-11-17 10:07:53 +0000
+++ src/comm.cc 2009-12-15 18:17:24 +0000
@@ -1991,6 +1991,9 @@
debugs(5, 5, "commHandleWrite: write() returns " << len);
fd_bytes(fd, len, FD_WRITE);
statCounter.syscalls.sock.writes++;
+ // After each successful partial write,
+ // reset fde::writeStart to the current time.
+ fd_table[fd].writeStart = squid_curtime;
if (len == 0) {
/* Note we even call write if nleft == 0 */
@@ -2062,6 +2065,7 @@
comm_io_callback_t *ccb = COMMIO_FD_WRITECB(fd);
assert(!ccb->active());
+ fd_table[fd].writeStart = squid_curtime;
/* Queue the write */
commio_set_callback(fd, IOCB_WRITE, ccb, callback,
(char *)buf, free_func, size);
@@ -2162,6 +2166,18 @@
return false;
}
+static bool
+writeTimedOut(int fd)
+{
+ if (!commio_has_callback(fd, IOCB_WRITE, COMMIO_FD_WRITECB(fd)))
+ return false;
+
+ if ((squid_curtime - fd_table[fd].writeStart) < Config.Timeout.write)
+ return false;
+
+ return true;
+}
+
void
checkTimeouts(void)
{
@@ -2172,7 +2188,11 @@
for (fd = 0; fd <= Biggest_FD; fd++) {
F = &fd_table[fd];
- if (AlreadyTimedOut(F))
+ if (writeTimedOut(fd)) {
+ // We have an active write callback and we are timed out
+ commio_finish_callback(fd, COMMIO_FD_WRITECB(fd), COMM_ERROR, ETIMEDOUT);
+ }
+ else if (AlreadyTimedOut(F))
continue;
debugs(5, 5, "checkTimeouts: FD " << fd << " Expired");
=== modified file 'src/fde.h'
--- src/fde.h 2009-01-07 11:24:40 +0000
+++ src/fde.h 2009-10-19 06:32:31 +0000
@@ -94,6 +94,7 @@
void *write_data;
AsyncCall::Pointer timeoutHandler;
time_t timeout;
+ time_t writeStart;
void *lifetime_data;
AsyncCall::Pointer closeHandler;
AsyncCall::Pointer halfClosedReader; /// read handler for half-closed fds
=== modified file 'src/structs.h'
--- src/structs.h 2009-11-22 20:37:27 +0000
+++ src/structs.h 2009-12-15 18:17:24 +0000
@@ -163,6 +163,7 @@
struct {
time_t read;
+ time_t write;
time_t lifetime;
time_t connect;
time_t forward;