From: Amos Jeffries Date: Mon, 21 Dec 2009 12:05:22 +0000 (+1300) Subject: Author: Tsantilas Christos X-Git-Tag: SQUID_3_2_0_1~498 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5ef5e5c;p=thirdparty%2Fsquid.git Author: Tsantilas Christos Add support for write timeouts. 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. --- diff --git a/src/cf.data.pre b/src/cf.data.pre index 79f17ff084..961d8689ec 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -3986,6 +3986,21 @@ DOC_START 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 diff --git a/src/comm.cc b/src/comm.cc index 3917b9514c..0bcf565cf2 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1991,6 +1991,9 @@ commHandleWrite(int fd, void *data) 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_write(int fd, const char *buf, int size, AsyncCall::Pointer &callback, FREE 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 @@ AlreadyTimedOut(fde *F) 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 @@ checkTimeouts(void) 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"); diff --git a/src/fde.h b/src/fde.h index 3b503d2b51..fa6ceff404 100644 --- a/src/fde.h +++ b/src/fde.h @@ -94,6 +94,7 @@ public: 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 diff --git a/src/structs.h b/src/structs.h index d9dafb6903..1168c464f6 100644 --- a/src/structs.h +++ b/src/structs.h @@ -165,6 +165,7 @@ struct SquidConfig { struct { time_t read; + time_t write; time_t lifetime; time_t connect; time_t forward;