Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

libevent2 http server how to detect client close

Tags:

http

libevent

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

like image 413
ideawu Avatar asked Mar 17 '26 13:03

ideawu


1 Answers

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.

like image 138
Anonymous Avatar answered Mar 20 '26 19:03

Anonymous



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!