=== modified file 'src/AccessLogEntry.h' --- src/AccessLogEntry.h 2009-08-23 09:30:49 +0000 +++ src/AccessLogEntry.h 2009-10-19 06:30:43 +0000 @@ -55,12 +55,20 @@ { public: - HttpDetails() : method(METHOD_NONE), code(0), content_type(NULL) {} + HttpDetails() : method(METHOD_NONE), code(0), content_type(NULL), + timedout(false), aborted(false) {} HttpRequestMethod method; int code; const char *content_type; HttpVersion version; + bool timedout; ///< terminated due to a lifetime or I/O timeout + bool aborted; ///< other abnormal termination (e.g., I/O error) + + /// compute suffix for the status access.log field + const char *statusSfx() const { + return timedout ? "_TIMEDOUT" : (aborted ? "_ABORTED" : ""); + } } http; class ICPDetails === modified file 'src/client_side.cc' --- src/client_side.cc 2009-11-18 12:37:56 +0000 +++ src/client_side.cc 2009-12-15 18:17:24 +0000 @@ -623,6 +623,15 @@ } } +/// propagates abort event to all contexts +void +ConnStateData::notifyAllContexts(int xerrno) +{ + typedef ClientSocketContext::Pointer CSCP; + for (CSCP c = getCurrentContext(); c.getRaw(); c = c->next) + c->noteIoError(xerrno); +} + /* This is a handler normally called by comm_close() */ void ConnStateData::connStateClosed(const CommCloseCbParams &io) { @@ -1622,6 +1631,19 @@ context->writeComplete (fd, bufnotused, size, errflag); } +/// remembers the abnormal connection termination for logging purposes +void +ClientSocketContext::noteIoError(const int xerrno) +{ + if (http) { + if (xerrno == ETIMEDOUT) + http->al.http.timedout = true; + else // even if xerrno is zero (which means read abort/eof) + http->al.http.aborted = true; + } +} + + void ClientSocketContext::doClose() { @@ -2215,6 +2237,7 @@ } else if (!Config.onoff.half_closed_clients) { /* admin doesn't want to support half-closed client sockets */ debugs(33, 3, "connFinishedWithConn: FD " << fd << " aborted (half_closed_clients disabled)"); + notifyAllContexts(0); // no specific error implies abort return 1; } } @@ -2663,6 +2686,7 @@ * lame half-close detection */ if (connReadWasError(io.flag, io.size, io.xerrno)) { + notifyAllContexts(io.xerrno); comm_close(fd); return; } @@ -2937,8 +2961,9 @@ clientLifetimeTimeout(int fd, void *data) { ClientHttpRequest *http = (ClientHttpRequest *)data; - debugs(33, 1, "WARNING: Closing client " << http->getConn()->peer << " connection due to lifetime timeout"); + debugs(33, 1, "WARNING: Closing client " << " connection due to lifetime timeout"); debugs(33, 1, "\t" << http->uri); + http->al.http.timedout = true; comm_close(fd); } === modified file 'src/client_side.h' --- src/client_side.h 2009-10-31 10:06:17 +0000 +++ src/client_side.h 2009-12-15 18:17:24 +0000 @@ -114,6 +114,7 @@ void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer receivedData); bool multipartRangeRequest() const; void registerWithConn(); + void noteIoError(const int xerrno); ///< update state to reflect I/O error private: CBDATA_CLASS(ClientSocketContext); @@ -142,6 +143,7 @@ int getAvailableBufferLength() const; bool areAllContextsForThisConnection() const; void freeAllContexts(); + void notifyAllContexts(const int xerrno); ///< tell everybody about the err void readNextRequest(); void makeSpaceAvailable(); ClientSocketContext::Pointer getCurrentContext() const; === modified file 'src/log/access_log.cc' --- src/log/access_log.cc 2009-11-22 20:37:27 +0000 +++ src/log/access_log.cc 2009-12-15 18:17:25 +0000 @@ -1047,7 +1047,13 @@ */ case LFT_SQUID_STATUS: - out = log_tags[al->cache.code]; + if (al->http.timedout || al->http.aborted) { + snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code], + al->http.statusSfx()); + out = tmp; + } else { + out = log_tags[al->cache.code]; + } break; @@ -1725,12 +1731,13 @@ safe_free(user); if (!Config.onoff.log_mime_hdrs) { - logfilePrintf(logfile, "%9ld.%03d %6d %s %s/%03d %"PRId64" %s %s %s %s%s/%s %s\n", + logfilePrintf(logfile, "%9ld.%03d %6d %s %s%s/%03d %"PRId64" %s %s %s %s%s/%s %s\n", (long int) current_time.tv_sec, (int) current_time.tv_usec / 1000, al->cache.msec, client, log_tags[al->cache.code], + al->http.statusSfx(), al->http.code, al->cache.replySize, al->_private.method_str, @@ -1743,12 +1750,13 @@ } else { char *ereq = log_quote(al->headers.request); char *erep = log_quote(al->headers.reply); - logfilePrintf(logfile, "%9ld.%03d %6d %s %s/%03d %"PRId64" %s %s %s %s%s/%s %s [%s] [%s]\n", + logfilePrintf(logfile, "%9ld.%03d %6d %s %s%s/%03d %"PRId64" %s %s %s %s%s/%s %s [%s] [%s]\n", (long int) current_time.tv_sec, (int) current_time.tv_usec / 1000, al->cache.msec, client, log_tags[al->cache.code], + al->http.statusSfx(), al->http.code, al->cache.replySize, al->_private.method_str, @@ -1785,7 +1793,7 @@ user2 = accessLogFormatName(al->cache.rfc931); - logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64" %s:%s", + logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64" %s%s:%s", client, user2 ? user2 : dash_str, user1 ? user1 : dash_str, @@ -1796,6 +1804,7 @@ al->http.code, al->cache.replySize, log_tags[al->cache.code], + al->http.statusSfx(), hier_code_str[al->hier.code]); safe_free(user1);