From: robertc <> Date: Fri, 15 Aug 2003 19:06:34 +0000 (+0000) Subject: Summary: Prevent pushing persistent connections with outstanding writes. X-Git-Tag: SQUID_3_0_PRE3~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=545d554b8625c3243e628dbcc76696a3526fd032;p=thirdparty%2Fsquid.git Summary: Prevent pushing persistent connections with outstanding writes. Keywords: Adrians' recent post to squid-dev looks like it's triggered by persistent connections being pushed inappropriately... this change adds an assert if a persistent connection is pushed while a write is outstanding. --- diff --git a/src/comm.cc b/src/comm.cc index eb3ec33bc3..3e0218503b 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1,6 +1,6 @@ /* - * $Id: comm.cc,v 1.386 2003/08/04 22:14:41 robertc Exp $ + * $Id: comm.cc,v 1.387 2003/08/15 13:06:34 robertc Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -159,6 +159,11 @@ public: CommRead read; + bool hasIncompleteWrite(); + + template + bool findCallback(P predicate); + CommWrite write; class Accept @@ -769,14 +774,31 @@ requireOpenAndActive(int const fd) * * Assumptions: the fd is open (ie, its not closing) */ + +struct FindReadCallback +{ + bool operator () (CommCallbackData *cd) + { + return cd->getType() == COMM_CB_READ; + } +}; + + int comm_has_pending_read_callback(int fd) { - dlink_node *node; - CommCallbackData *cd; - requireOpenAndActive(fd); + if (fdc_table[fd].findCallback(FindReadCallback())) + return 1; + + return 0; +} + +template +bool +fdc_t::findCallback(P predicate) +{ /* * XXX I don't like having to walk the list! * Instead, if this routine is called often enough, we should @@ -784,19 +806,17 @@ comm_has_pending_read_callback(int fd) * check if the list head a HEAD.. * - adrian */ - node = fdc_table[fd].CommCallbackList.head; + dlink_node *node = CommCallbackList.head; while (node != NULL) { - cd = (CommCallbackData *)node->data; - - if (cd->getType() == COMM_CB_READ) - return 1; + if (predicate((CommCallbackData *)node->data)) + return true; node = node->next; } /* Not found */ - return 0; + return false; } /* @@ -880,6 +900,32 @@ comm_udp_send(int s, const void *buf, size_t len, int flags) /* * The new-style comm_write magic */ + +struct FindWriteCallback +{ + bool operator () (CommCallbackData *cd) + { + return dynamic_cast(cd) != NULL; + } +}; + +bool +comm_has_incomplete_write(int fd) +{ + requireOpenAndActive(fd); + + if (fdc_table[fd].hasIncompleteWrite()) + return true; + + return (fdc_table[fd].findCallback(FindWriteCallback())); +} + +bool +fdc_t::hasIncompleteWrite() +{ + return write.handler != NULL; +} + /* * Attempt a write * @@ -936,6 +982,9 @@ comm_write(int fd, const char *buf, size_t size, IOWCB *handler, void *handler_d assert(fdc_table[fd].write.handler == NULL); assert(!fd_table[fd].flags.closing); + /* Can't queue a write with no callback */ + assert(handler); + /* Queue a read */ fdc_table[fd].write.buf = buf; fdc_table[fd].write.size = size; diff --git a/src/comm.h b/src/comm.h index e31f0c2dcb..cba1328e32 100644 --- a/src/comm.h +++ b/src/comm.h @@ -30,6 +30,7 @@ extern void comm_accept_setcheckperiod(int fd, int mdelay); extern void comm_write(int s, const char *buf, size_t len, IOWCB *callback, void *callback_data); #include "Store.h" extern void commMarkHalfClosed(int); +extern bool comm_has_incomplete_write(int); /* Where should this belong? */ diff --git a/src/pconn.cc b/src/pconn.cc index 54c0a8d748..3a2d9c0ebd 100644 --- a/src/pconn.cc +++ b/src/pconn.cc @@ -1,6 +1,6 @@ /* - * $Id: pconn.cc,v 1.39 2003/06/23 12:11:45 robertc Exp $ + * $Id: pconn.cc,v 1.40 2003/08/15 13:06:34 robertc Exp $ * * DEBUG: section 48 Persistent Connections * AUTHOR: Duane Wessels @@ -282,6 +282,7 @@ pconnPush(int fd, const char *host, u_short port, const char *domain) xfree(old); } + assert(!comm_has_incomplete_write(fd)); p->fds[p->nfds++] = fd; comm_read(fd, p->buf, BUFSIZ, pconnRead, p); commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p);