[Libevent-users] evhttp chunked response bug?
Hi, there, I'm reading evhttp's source code, and I'm not sure if I've found a bug, or I just mis-read it. But it seems to me, when I do chunked encoding on response, I'd call three functions sequentially somehow, evhttp_send_reply_start(req, ...); evhttp_send_reply_chunk(req, ...); evhttp_send_reply_end(req, ...); Here's the problem, if any of the 1st two fails to send some packets, i.e., evbuffer_write() returned -1 or 0, it will call evhttp_connection_fail(), which will free the request eventually if connection needs to be closed by evhttp_connection_free(). Now, how does my subsequent call know req is freed? Wouldn't that cause crashes, if I simply call those 3 functions in a row? Or did I miss some correct way of calling them? Thanks. -Haiping ___ Libevent-users mailing list Libevent-users@monkey.org http://monkeymail.org/mailman/listinfo/libevent-users
Re: [Libevent-users] evhttp chunked response bug?
If this turned out to be a real bug, I made a change that might help: [hz...@dev066 libevent-1.4.11-stable]$ svn diff Index: http.c === --- http.c (revision 184899) +++ http.c (working copy) @@ -1976,6 +1976,8 @@ evhttp_send_reply_start(struct evhttp_request *req, int code, const char *reason) { + req-referenced = 1; + evhttp_response_code(req, code, reason); if (req-major == 1 req-minor == 1) { /* use chunked encoding for HTTP/1.1 */ @@ -1990,6 +1992,8 @@ void evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf) { + if (req-referenced 0) return; + if (req-chunked) { evbuffer_add_printf(req-evcon-output_buffer, %x\r\n, (unsigned)EVBUFFER_LENGTH(databuf)); @@ -2004,6 +2008,12 @@ void evhttp_send_reply_end(struct evhttp_request *req) { + if (req-referenced 0) { +req-referenced = 0; +evhttp_request_free(req); +return; + } + struct evhttp_connection *evcon = req-evcon; if (req-chunked) { @@ -2547,6 +2557,11 @@ void evhttp_request_free(struct evhttp_request *req) { + if (req-referenced) { +req-referenced = -1; +return; + } + if (req-remote_host != NULL) free(req-remote_host); if (req-uri != NULL) Index: evhttp.h === --- evhttp.h(revision 184899) +++ evhttp.h(working copy) @@ -261,6 +261,7 @@ struct evbuffer *input_buffer; /* read data */ ev_int64_t ntoread; int chunked; + int referenced; struct evbuffer *output_buffer; /* outgoing post or data */ On 9/3/09 11:40 PM, Haiping Zhao hz...@facebook.com wrote: Hi, there, I'm reading evhttp's source code, and I'm not sure if I've found a bug, or I just mis-read it. But it seems to me, when I do chunked encoding on response, I'd call three functions sequentially somehow, evhttp_send_reply_start(req, ...); evhttp_send_reply_chunk(req, ...); evhttp_send_reply_end(req, ...); Here's the problem, if any of the 1st two fails to send some packets, i.e., evbuffer_write() returned -1 or 0, it will call evhttp_connection_fail(), which will free the request eventually if connection needs to be closed by evhttp_connection_free(). Now, how does my subsequent call know req is freed? Wouldn't that cause crashes, if I simply call those 3 functions in a row? Or did I miss some correct way of calling them? Thanks. -Haiping ___ Libevent-users mailing list Libevent-users@monkey.org http://monkeymail.org/mailman/listinfo/libevent-users
Re: [Libevent-users] evhttp chunked response bug?
Shouldn't you call evhttp_send_reply_end in the callback of evhttp_send_reply_chunk which is only called if the sending succeeded? On 9/4/09, Haiping Zhao hz...@facebook.com wrote: Hi, there, I'm reading evhttp's source code, and I'm not sure if I've found a bug, or I just mis-read it. But it seems to me, when I do chunked encoding on response, I'd call three functions sequentially somehow, evhttp_send_reply_start(req, ...); evhttp_send_reply_chunk(req, ...); evhttp_send_reply_end(req, ...); Here's the problem, if any of the 1st two fails to send some packets, i.e., evbuffer_write() returned -1 or 0, it will call evhttp_connection_fail(), which will free the request eventually if connection needs to be closed by evhttp_connection_free(). Now, how does my subsequent call know req is freed? Wouldn't that cause crashes, if I simply call those 3 functions in a row? Or did I miss some correct way of calling them? Thanks. -Haiping ___ Libevent-users mailing list Libevent-users@monkey.org http://monkeymail.org/mailman/listinfo/libevent-users ___ Libevent-users mailing list Libevent-users@monkey.org http://monkeymail.org/mailman/listinfo/libevent-users
Re: [Libevent-users] evhttp chunked response bug?
Hmm, that should help. I have several send_reply_chunk() though. Are you suggesting they should form nested callback chains? -Haiping On 9/4/09 3:19 PM, q6Yr7e0o nIJDVMjC u9oqc...@googlemail.com wrote: Shouldn't you call evhttp_send_reply_end in the callback of evhttp_send_reply_chunk which is only called if the sending succeeded? On 9/4/09, Haiping Zhao hz...@facebook.com wrote: Hi, there, I'm reading evhttp's source code, and I'm not sure if I've found a bug, or I just mis-read it. But it seems to me, when I do chunked encoding on response, I'd call three functions sequentially somehow, evhttp_send_reply_start(req, ...); evhttp_send_reply_chunk(req, ...); evhttp_send_reply_end(req, ...); Here's the problem, if any of the 1st two fails to send some packets, i.e., evbuffer_write() returned -1 or 0, it will call evhttp_connection_fail(), which will free the request eventually if connection needs to be closed by evhttp_connection_free(). Now, how does my subsequent call know req is freed? Wouldn't that cause crashes, if I simply call those 3 functions in a row? Or did I miss some correct way of calling them? Thanks. -Haiping ___ Libevent-users mailing list Libevent-users@monkey.org http://monkeymail.org/mailman/listinfo/libevent-users ___ Libevent-users mailing list Libevent-users@monkey.org http://monkeymail.org/mailman/listinfo/libevent-users
Re: [Libevent-users] evhttp chunked response bug?
Hi, Hmm, that should help. I have several send_reply_chunk() though. Are you suggesting they should form nested callback chains? Afaik it's the only threadsafe way of ensuring to not call reads and writes on already closed descriptors. Although i know it's highly unportable i use gcc's nested functions [1] for such kind of callbacks; it's just extremly nice to read. As long as GCC's your compiler nested functions are great for callbacks. Just never reference data outside the function's scope :-) [1] http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html ___ Libevent-users mailing list Libevent-users@monkey.org http://monkeymail.org/mailman/listinfo/libevent-users