Commit 4e2f3f2d authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@595 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent d7225af7
......@@ -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);
......
......@@ -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 *
......
......@@ -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);
......
......@@ -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);
}
/*--------------------------------------------------------------------
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment