]> granicus.if.org Git - libevent/commitdiff
allow gotsig to terminate active event loop;
authorNiels Provos <provos@gmail.com>
Wed, 6 Dec 2006 03:38:41 +0000 (03:38 +0000)
committerNiels Provos <provos@gmail.com>
Wed, 6 Dec 2006 03:38:41 +0000 (03:38 +0000)
free http connection on failed incoming connections;
bugs pointed out by Dug Song.

svn:r293

event.c
http.c

diff --git a/event.c b/event.c
index 864d4d267e63c63b4d96caf8278391ec67e76236..90f88ab6bd38c3ce1641ade8e6448bdddc2e14d1 100644 (file)
--- a/event.c
+++ b/event.c
@@ -311,6 +311,8 @@ event_process_active(struct event_base *base)
                        ncalls--;
                        ev->ev_ncalls = ncalls;
                        (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
+                       if (event_gotsig)
+                               return;
                }
        }
 }
diff --git a/http.c b/http.c
index aec8df37811d2de9eaba1236e22eda80f9726829..429964611268d57f761d6acd3c9db483aaca0e6c 100644 (file)
--- a/http.c
+++ b/http.c
@@ -426,10 +426,10 @@ evhttp_connection_incoming_fail(struct evhttp_request *req,
        case EVCON_HTTP_TIMEOUT:
        case EVCON_HTTP_EOF:
                /* 
-                * these are cases in which we probably should just close
-                * the connection and actually send a reply.  this case may
-                * happen when a browser keeps a persistent connection open
-                * and we timeout on the read.
+                * these are cases in which we probably should just
+                * close the connection and not send a reply.  this
+                * case may happen when a browser keeps a persistent
+                * connection open and we timeout on the read.
                 */
                return (-1);
        case EVCON_HTTP_INVALID_HEADER:
@@ -439,6 +439,11 @@ evhttp_connection_incoming_fail(struct evhttp_request *req,
                        free(req->uri);
                        req->uri = NULL;
                }
+
+               /* 
+                * the callback needs to send a reply, once the reply has
+                * been send, the connection should get freed.
+                */
                (*req->cb)(req, req->cb_arg);
        }
        
@@ -452,28 +457,31 @@ evhttp_connection_fail(struct evhttp_connection *evcon,
        struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
        assert(req != NULL);
        
-       if (req->cb != NULL) {
+       if (evcon->flags & EVHTTP_CON_INCOMING) {
                /* 
-                * we are passing the request object if we have an incoming
-                * request that somehow needs to be answered.  we need to
-                * wait for the answer to travel over the wire before we can
-                * kill the connection.
+                * for incoming requests, there are two different
+                * failure cases.  it's either a network level error
+                * or an http layer error. for problems on the network
+                * layer like timeouts we just drop the connections.
+                * For HTTP problems, we might have to send back a
+                * reply before the connection can be freed.
                 */
-               if (evcon->flags & EVHTTP_CON_INCOMING) {
-                       if (evhttp_connection_incoming_fail(req, error) == 0)
-                               return;
-               } else {
-                       (*req->cb)(NULL, req->cb_arg);
-               }
+               if (evhttp_connection_incoming_fail(req, error) == -1)
+                       evhttp_connection_free(evcon);
+               return;
        }
 
-       /* reset the connection */
-       evhttp_connection_reset(evcon);
+
+       if (req->cb != NULL)
+               (*req->cb)(NULL, req->cb_arg);
 
        TAILQ_REMOVE(&evcon->requests, req, next);
        evhttp_request_free(req);
 
        /* xxx: maybe we should fail all requests??? */
+
+       /* reset the connection */
+       evhttp_connection_reset(evcon);
        
        /* We are trying the next request that was queued on us */
        if (TAILQ_FIRST(&evcon->requests) != NULL)
@@ -626,6 +634,14 @@ evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
 void
 evhttp_connection_free(struct evhttp_connection *evcon)
 {
+       struct evhttp_request *req;
+
+       /* remove all requests that might be queued on this connection */
+       while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
+               TAILQ_REMOVE(&evcon->requests, req, next);
+               evhttp_request_free(req);
+       }
+
        if (evcon->http_server != NULL) {
                struct evhttp *http = evcon->http_server;
                TAILQ_REMOVE(&http->connections, evcon, next);