From 89fc97cb6c8f763a271b1fe0d8915ccda1817372 Mon Sep 17 00:00:00 2001 From: phk Date: Wed, 2 Aug 2006 07:07:56 +0000 Subject: [PATCH] I have nothing but circumstantial evidence that libevent is involved in the current stack corruption I see, but we might as well avoid using it where we can: Don't engage the eventengine when we talk to the backend, just call read(2) directly. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@595 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 3 +- varnish-cache/bin/varnishd/cache_acceptor.c | 4 +- varnish-cache/bin/varnishd/cache_fetch.c | 9 +- varnish-cache/bin/varnishd/cache_http.c | 138 ++++++++++++-------- varnish-cache/bin/varnishd/cache_pass.c | 8 +- 5 files changed, 94 insertions(+), 68 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index da36a24b..d9bfb8fb 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -347,7 +347,8 @@ int http_GetStatus(struct http *hp); int http_HdrIs(struct http *hp, const char *hdr, const char *val); int http_GetTail(struct http *hp, unsigned len, char **b, char **e); int http_Read(struct http *hp, int fd, void *b, unsigned len); -void http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg); +void http_RecvHeadEv(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg); +int http_RecvHead(struct http *hp, int fd); int http_DissectRequest(struct http *sp, int fd); int http_DissectResponse(struct http *sp, int fd); diff --git a/varnish-cache/bin/varnishd/cache_acceptor.c b/varnish-cache/bin/varnishd/cache_acceptor.c index 9080d032..6a3a121a 100644 --- a/varnish-cache/bin/varnishd/cache_acceptor.c +++ b/varnish-cache/bin/varnishd/cache_acceptor.c @@ -92,7 +92,7 @@ pipe_f(int fd, short event, void *arg) assert(i == sizeof sp); clock_gettime(CLOCK_MONOTONIC, &sp->t_idle); TAILQ_INSERT_TAIL(&sesshead, sp, list); - http_RecvHead(sp->http, sp->fd, evb, vca_callback, sp); + http_RecvHeadEv(sp->http, sp->fd, evb, vca_callback, sp); } static void @@ -136,7 +136,7 @@ accept_f(int fd, short event, void *arg) VSL(SLT_SessionOpen, sp->fd, "%s %s", sp->addr, sp->port); clock_gettime(CLOCK_MONOTONIC, &sp->t_idle); TAILQ_INSERT_TAIL(&sesshead, sp, list); - http_RecvHead(sp->http, sp->fd, evb, vca_callback, sp); + http_RecvHeadEv(sp->http, sp->fd, evb, vca_callback, sp); } static void * diff --git a/varnish-cache/bin/varnishd/cache_fetch.c b/varnish-cache/bin/varnishd/cache_fetch.c index 5a0724b1..c5c17032 100644 --- a/varnish-cache/bin/varnishd/cache_fetch.c +++ b/varnish-cache/bin/varnishd/cache_fetch.c @@ -296,12 +296,9 @@ FetchHeaders(struct sess *sp) CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC); - /* - * XXX: It might be cheaper to avoid the event_engine and simply - * XXX: read(2) the header - */ - http_RecvHead(vc->http, vc->fd, w->eb, NULL, NULL); - (void)event_base_loop(w->eb, 0); + + i = http_RecvHead(vc->http, vc->fd); + assert(i == 0); assert(http_DissectResponse(vc->http, vc->fd) == 0); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); diff --git a/varnish-cache/bin/varnishd/cache_http.c b/varnish-cache/bin/varnishd/cache_http.c index ffa251bc..99de6a1d 100644 --- a/varnish-cache/bin/varnishd/cache_http.c +++ b/varnish-cache/bin/varnishd/cache_http.c @@ -440,19 +440,36 @@ http_header_complete(struct http *hp) return (1); } - /*--------------------------------------------------------------------*/ static void -http_read_f(int fd, short event, void *arg) +http_preprecv(struct http *hp) { - struct http *hp; unsigned l; - int i, ret = 0; - (void)event; + CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); + assert(hp->v <= hp->e); + assert(hp->t <= hp->v); + if (hp->t > hp->s && hp->t < hp->v) { + l = hp->v - hp->t; + memmove(hp->s, hp->t, l); + hp->v = hp->s + l; + hp->t = hp->s; + *hp->v = '\0'; + } else { + hp->v = hp->s; + hp->t = hp->s; + } +} + +/*--------------------------------------------------------------------*/ + +static int +http_read_hdr(int fd, struct http *hp) +{ + unsigned l; + int i; - CAST_OBJ_NOTNULL(hp, arg, HTTP_MAGIC); l = (hp->e - hp->s) / 2; if (l < hp->v - hp->s) l = 0; @@ -462,70 +479,85 @@ http_read_f(int fd, short event, void *arg) VSL(SLT_HttpError, fd, "Received too much"); VSLR(SLT_HttpGarbage, fd, hp->s, hp->v); hp->t = NULL; - ret = 1; - } else { - errno = 0; - i = read(fd, hp->v, l - 1); - if (i > 0) { - hp->v += i; - *hp->v = '\0'; - if (!http_header_complete(hp)) - return; - } else { - if (hp->v != hp->s) { - VSL(SLT_HttpError, fd, - "Received (only) %d bytes, errno %d", - hp->v - hp->s, errno); - VSLR(SLT_Debug, fd, hp->s, hp->v); - } else if (errno == 0) - VSL(SLT_HttpError, fd, "Received nothing"); - else - VSL(SLT_HttpError, fd, - "Received errno %d", errno); - hp->t = NULL; - ret = 2; - } + return (1); } + errno = 0; + i = read(fd, hp->v, l - 1); + if (i > 0) { + hp->v += i; + *hp->v = '\0'; + if (http_header_complete(hp)) + return(0); + return (-1); + } + + if (hp->v != hp->s) { + VSL(SLT_HttpError, fd, + "Received (only) %d bytes, errno %d", + hp->v - hp->s, errno); + VSLR(SLT_Debug, fd, hp->s, hp->v); + } else if (errno == 0) + VSL(SLT_HttpError, fd, "Received nothing"); + else + VSL(SLT_HttpError, fd, + "Received errno %d", errno); + hp->t = NULL; + return(2); +} + +/*--------------------------------------------------------------------*/ + +static void +http_read_f(int fd, short event, void *arg) +{ + struct http *hp; + int i; + + (void)event; + + CAST_OBJ_NOTNULL(hp, arg, HTTP_MAGIC); + i = http_read_hdr(fd, hp); + if (i < 0) + return; - assert(hp->t != NULL || ret != 0); event_del(&hp->ev); if (hp->callback != NULL) - hp->callback(hp->arg, ret); + hp->callback(hp->arg, i); } -/*--------------------------------------------------------------------*/ void -http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg) +http_RecvHeadEv(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg) { - unsigned l; CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); - assert(hp->v <= hp->e); - assert(hp->t <= hp->v); - if (0) - VSL(SLT_Debug, fd, "Recv t %u v %u", - hp->t - hp->s, hp->v - hp->s); - if (hp->t > hp->s && hp->t < hp->v) { - l = hp->v - hp->t; - memmove(hp->s, hp->t, l); - hp->v = hp->s + l; - hp->t = hp->s; - *hp->v = '\0'; - if (http_header_complete(hp)) { - assert(func != NULL); - func(arg, 0); - return; - } - } else { - hp->v = hp->s; - hp->t = hp->s; + assert(func != NULL); + http_preprecv(hp); + if (hp->v != hp->s && http_header_complete(hp)) { + func(arg, 0); + return; } hp->callback = func; hp->arg = arg; event_set(&hp->ev, fd, EV_READ | EV_PERSIST, http_read_f, hp); AZ(event_base_set(eb, &hp->ev)); AZ(event_add(&hp->ev, NULL)); /* XXX: timeout */ + return; +} + +/*--------------------------------------------------------------------*/ + +int +http_RecvHead(struct http *hp, int fd) +{ + int i; + + CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); + http_preprecv(hp); + do + i = http_read_hdr(fd, hp); + while (i == -1); + return (i); } /*-------------------------------------------------------------------- diff --git a/varnish-cache/bin/varnishd/cache_pass.c b/varnish-cache/bin/varnishd/cache_pass.c index f92b1cb5..d0656ae3 100644 --- a/varnish-cache/bin/varnishd/cache_pass.c +++ b/varnish-cache/bin/varnishd/cache_pass.c @@ -205,12 +205,8 @@ PassSession(struct sess *sp) /* XXX: copy any contents */ - /* - * XXX: It might be cheaper to avoid the event_engine and simply - * XXX: read(2) the header - */ - http_RecvHead(vc->http, vc->fd, w->eb, NULL, NULL); - (void)event_base_loop(w->eb, 0); + i = http_RecvHead(vc->http, vc->fd); + assert(i == 0); http_DissectResponse(vc->http, vc->fd); sp->vbc = vc; -- 2.39.5