=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2009-11-12 12:49:09 +0000
+++ src/cf.data.pre	2009-12-20 21:18:26 +0000
@@ -3868,6 +3868,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-21 11:01:43 +0000
+++ src/comm.cc	2009-12-20 21:18:26 +0000
@@ -1984,6 +1984,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 */
@@ -2055,6 +2058,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);
@@ -2155,6 +2159,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)
 {
@@ -2165,7 +2181,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-16 12:14:02 +0000
+++ src/fde.h	2009-12-20 21:18:26 +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-09-27 00:28:52 +0000
+++ src/structs.h	2009-12-20 21:18:26 +0000
@@ -160,6 +160,7 @@
 
     struct {
         time_t read;
+        time_t write;
         time_t lifetime;
         time_t connect;
         time_t forward;




