libevent2 http server how to detect client close

2.2k Views Asked by At

I write a simple web server that handles long-polling, which means the server doesn't send a full HTTP response to the client(web browser, curl, etc), but only sends HTTP headers and hang the connection.

I use command line curl to product a request to the server, it prints out HTTP response headers well, and curl hangs as expected. Then I press CTRL+C to terminate the curl process. But the server never knows this close(on_disconnect() is never called).

Some of the codes:

void request_handler(struct evhttp_request *req, void *arg){
    // only send response headers, and one piece of chunked data
    evhttp_send_reply_start(req, HTTP_OK, "OK");
    evbuffer_add_printf(buf, "...\n");
    evhttp_send_reply_chunk(req, buf);
    // register connection close callback
    evhttp_connection_set_closecb(req->evcon, on_disconnect, sub);
}

void on_disconnect(struct evhttp_connection *evcon, void *arg){
    printf("disconnected\n");
}

evhttp_set_gencb(http, request_handler, NULL);

My question is, how to detect this kind of client close(a TCP FIN received)?

Bug at github

1

There are 1 best solutions below

4
On

I think that this is a bug in libevent.

I have a similar issue with libevent 2.0.21, and here's what happens in my case: When evhttp_read_header() in libevent's http.c is done reading the HTTP headers from the client, it disables any future read events by calling bufferevent_disable(..., EV_READ). However, read events need to be enabled for the underlying bufferevent to report EOF. That's why the bufferevent never tells libevent's HTTP code when the client closes the connection.

I fixed the issue in my case by simply removing the call to bufferevent_disable() in evhttp_read_header(). I use "Connection: close" and nothing but GET requests, so the client never sends any data after the headers and this solution seems to work well for this very specific and simple use case. I am not sure, however, that this doesn't break other use cases, especially when you use persistent connections or things like "Expect: 100-continue".

You may want to take this to the libevent mailing list.