=== 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;