[4.0] 47d66bb Introduce http->failed to mark struct http's suffering from trouble.

Poul-Henning Kamp phk at FreeBSD.org
Tue Jun 24 11:31:54 CEST 2014


commit 47d66bb472669e4def4c180cd349e0552d3b4451
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Jun 3 11:55:18 2014 +0000

    Introduce http->failed to mark struct http's suffering from trouble.
    
    Usually, (probably always) this means failure to get workspace for
    modifications of the http.
    
    The intent is that this flag will have the same "latching" behaviour
    as error handling in VSB's:  Once set, it stays set and nobody
    reads or writes the struct http any more.
    
    Setting the flag causes a SLT_Error message.
    
    Rewrite http_CollectHdr() to respect failed and optimize it
    slightly while were here.

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index a82ea69..979eedd 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -202,6 +202,7 @@ struct http {
 	uint16_t		status;
 	uint8_t			protover;
 	uint8_t			conds;		/* If-* headers present */
+	uint8_t			failed;		/* usually: ws-alloc failed */
 };
 
 /*--------------------------------------------------------------------
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 88ff577..49522cd 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -93,6 +93,15 @@ http_VSL_log(const struct http *hp)
 }
 
 /*--------------------------------------------------------------------*/
+
+static void
+http_fail(struct http *hp)
+{
+	VSLb(hp->vsl, SLT_Error, "out of workspace");
+	hp->failed = 1;
+}
+
+/*--------------------------------------------------------------------*/
 /* List of canonical HTTP response code names from RFC2616 */
 
 static struct http_msg {
@@ -146,12 +155,17 @@ HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
     enum VSL_tag_e  whence)
 {
 	http_Teardown(hp);
+	hp->nhd = HTTP_HDR_FIRST;
 	hp->logtag = whence;
 	hp->ws = ws;
 	hp->vsl = vsl;
 }
 
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * http_Teardown() is a safety feature, we use it to zap all http
+ * structs once we're done with them, to minimize the risk that
+ * old stale pointers exist to no longer valid stuff.
+ */
 
 void
 http_Teardown(struct http *hp)
@@ -162,7 +176,6 @@ http_Teardown(struct http *hp)
 	memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
 	memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
 	memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
-	hp->nhd = HTTP_HDR_FIRST;
 }
 
 /*--------------------------------------------------------------------*/
@@ -181,6 +194,26 @@ http_IsHdr(const txt *hh, const char *hdr)
 	return (!strncasecmp(hdr, hh->b, l));
 }
 
+/*--------------------------------------------------------------------*/
+
+static unsigned
+http_findhdr(const struct http *hp, unsigned l, const char *hdr)
+{
+	unsigned u;
+
+	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
+		Tcheck(hp->hd[u]);
+		if (hp->hd[u].e < hp->hd[u].b + l + 1)
+			continue;
+		if (hp->hd[u].b[l] != ':')
+			continue;
+		if (strncasecmp(hdr, hp->hd[u].b, l))
+			continue;
+		return (u);
+	}
+	return (0);
+}
+
 /*--------------------------------------------------------------------
  * This function collapses multiple headerlines of the same name.
  * The lines are joined with a comma, according to [rfc2616, 4.2bot, p32]
@@ -189,57 +222,60 @@ http_IsHdr(const txt *hh, const char *hdr)
 void
 http_CollectHdr(struct http *hp, const char *hdr)
 {
-	unsigned u, v, ml, f = 0, x;
+	unsigned u, l, ml, f, x, d;
 	char *b = NULL, *e = NULL;
 
-	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
-		while (u < hp->nhd && http_IsHdr(&hp->hd[u], hdr)) {
-			Tcheck(hp->hd[u]);
-			if (f == 0) {
-				/* Found first header, just record the fact */
-				f = u;
-				break;
-			}
-			if (b == NULL) {
-				/* Found second header, start our collection */
-				ml = WS_Reserve(hp->ws, 0);
-				b = hp->ws->f;
-				e = b + ml;
-				x = Tlen(hp->hd[f]);
-				if (b + x < e) {
-					memcpy(b, hp->hd[f].b, x);
-					b += x;
-				} else
-					b = e;
-			}
+	if (hp->failed)
+		return;
+	l = hdr[0];
+	assert(l == strlen(hdr + 1));
+	assert(hdr[l] == ':');
+	f = http_findhdr(hp, l - 1, hdr + 1);
+	if (f == 0)
+		return;
 
-			AN(b);
-			AN(e);
-
-			/* Append the Nth header we found */
-			if (b < e)
-				*b++ = ',';
-			x = Tlen(hp->hd[u]) - *hdr;
-			if (b + x < e) {
-				memcpy(b, hp->hd[u].b + *hdr, x);
-				b += x;
-			} else
-				b = e;
-
-			/* Shift remaining headers up one slot */
-			for (v = u; v < hp->nhd - 1; v++)
-				hp->hd[v] = hp->hd[v + 1];
-			hp->nhd--;
+	for (d = u = f + 1; u < hp->nhd; u++) {
+		Tcheck(hp->hd[u]);
+		if (!http_IsHdr(&hp->hd[u], hdr)) {
+			if (d != u)
+				hp->hd[d] = hp->hd[u];
+			d++;
+			continue;
+		}
+		if (b == NULL) {
+			/* Found second header, start our collection */
+			ml = WS_Reserve(hp->ws, 0);
+			b = hp->ws->f;
+			e = b + ml;
+			x = Tlen(hp->hd[f]);
+			if (b + x >= e) {
+				http_fail(hp);
+				WS_Release(hp->ws, 0);
+				return;
+			}
+			memcpy(b, hp->hd[f].b, x);
+			b += x;
 		}
 
+		AN(b);
+		AN(e);
+
+		/* Append the Nth header we found */
+		if (b < e)
+			*b++ = ',';
+		x = Tlen(hp->hd[u]) - l;
+		if (b + x >= e) {
+			http_fail(hp);
+			WS_Release(hp->ws, 0);
+			return;
+		}
+		memcpy(b, hp->hd[u].b + *hdr, x);
+		b += x;
 	}
 	if (b == NULL)
 		return;
+	hp->nhd = (uint16_t)d;
 	AN(e);
-	if (b >= e) {
-		WS_Release(hp->ws, 0);
-		return;
-	}
 	*b = '\0';
 	hp->hd[f].b = hp->ws->f;
 	hp->hd[f].e = b;
@@ -248,24 +284,6 @@ http_CollectHdr(struct http *hp, const char *hdr)
 
 /*--------------------------------------------------------------------*/
 
-static unsigned
-http_findhdr(const struct http *hp, unsigned l, const char *hdr)
-{
-	unsigned u;
-
-	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
-		Tcheck(hp->hd[u]);
-		if (hp->hd[u].e < hp->hd[u].b + l + 1)
-			continue;
-		if (hp->hd[u].b[l] != ':')
-			continue;
-		if (strncasecmp(hdr, hp->hd[u].b, l))
-			continue;
-		return (u);
-	}
-	return (0);
-}
-
 int
 http_GetHdr(const struct http *hp, const char *hdr, char **ptr)
 {



More information about the varnish-commit mailing list