From d58f77ad52caa52e91cf698e60a5a43c5d870e84 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 23 May 2013 12:41:03 +0200 Subject: relay: fix close handling When the relay process has exited, close the connection as soon as no data can immediately be read from the socket anymore, and the read buffer has been emptied. This fixes timeouts with scripts that leave processes lingering around without closing their fds. Signed-off-by: Felix Fietkau --- relay.c | 17 ++++++++++++----- uhttpd.h | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/relay.c b/relay.c index 83664e6..1b55d41 100644 --- a/relay.c +++ b/relay.c @@ -115,6 +115,9 @@ static void relay_read_cb(struct ustream *s, int bytes) char *buf; int len; + if (r->process_done) + uloop_timeout_set(&r->timeout, 1); + relay_process_headers(r); if (r->header_cb) { @@ -140,11 +143,14 @@ static void relay_read_cb(struct ustream *s, int bytes) ustream_consume(s, len); } -static void relay_close_if_done(struct relay *r) +static void relay_close_if_done(struct uloop_timeout *timeout) { + struct relay *r = container_of(timeout, struct relay, timeout); struct ustream *s = &r->sfd.stream; - if (!s->eof || ustream_pending_data(s, false)) + while (ustream_poll(&r->sfd.stream)); + + if (!(r->process_done || s->eof) || ustream_pending_data(s, false)) return; uh_relay_close(r, r->ret); @@ -155,17 +161,16 @@ static void relay_state_cb(struct ustream *s) struct relay *r = container_of(s, struct relay, sfd.stream); if (r->process_done) - relay_close_if_done(r); + uloop_timeout_set(&r->timeout, 1); } static void relay_proc_cb(struct uloop_process *proc, int ret) { struct relay *r = container_of(proc, struct relay, proc); - ustream_poll(&r->sfd.stream); r->process_done = true; r->ret = ret; - relay_close_if_done(r); + uloop_timeout_set(&r->timeout, 1); } void uh_relay_kill(struct client *cl, struct relay *r) @@ -190,4 +195,6 @@ void uh_relay_open(struct client *cl, struct relay *r, int fd, int pid) r->proc.pid = pid; r->proc.cb = relay_proc_cb; uloop_process_add(&r->proc); + + r->timeout.cb = relay_close_if_done; } diff --git a/uhttpd.h b/uhttpd.h index d6b6985..59f1565 100644 --- a/uhttpd.h +++ b/uhttpd.h @@ -146,6 +146,7 @@ struct env_var { struct relay { struct ustream_fd sfd; struct uloop_process proc; + struct uloop_timeout timeout; struct client *cl; bool process_done; -- cgit v1.2.3