Hi, Any help on this please?
Regards, Alap ________________________________ From: Alap Kumar Sinha <ala...@yahoo.com> To: "libevent-us...@freehaven.net" <libevent-us...@freehaven.net> Sent: Wednesday, May 23, 2012 10:24 AM Subject: Crash in evhttp_send_reply_chunk() Hi, I am using libevent to implement a HTTP server. I am observing a crash & connection disconnect in libevent in the following scenario. 1. The process starts a libevent HTTP server & registers for callbacks for different URLs. 2. For one of the GET request from the client, the server needs to keep the connection open & send chunk replies as when data from some other source arrive. 3. So it does a *_reply_start() & then *_reply_chunk() when data is available Everything works fine at the beginning , but after a while (random could in 30 mins or couple of hours) observe the following issues 1. 1.The libevent crashes. Checked the core dump analysis of multiple crashes & it points to the following code. a. 0x0042b0a8 in evbuffer_add_buffer (outbuf=0x4924b8, inbuf=0x496428) at buffer.c:774 2. Sometimes the connection between server & client gets disconnected. When checked through wireshark, observed a FIN ACK coming from the HTTP server. Below is a simplified code snippet showcasing the implementation & use case. I would appreciate if someone could let know, if I am doing something wrong in the usage of the libevent APIs & what could be the cause of the crash. #define KEY_STRING "CHECK" struct evhttp_request *req; //Structure holds the req, on which chunk reply is sent pthread_t SenderThread; bool startSend = false; void connectionClosed(struct evhttp_connection* evcon, void* key) { printf("Connection closed by client"); } //****** Function to send some data every 5 secs************/ void sendChunk(struct evhttp_connection* evcon, void* key) { int counter = 0; printf("Start sending data everyy 5 secs"); while(1) { if(startSend) //startSend is set to true when client does a GET & SSEEvents_cb() is invoked { evbuffer *databuf = evbuffer_new(); if (databuf != NULL) { evbuffer_add(databuf,"event:remoteEvent\n",strlen("event:remoteEvent\n")); evbuffer_add_printf(databuf,"data:TestDATA%d\n",counter); evhttp_send_reply_chunk(req, databuf); evbuffer_free(databuf); counter++; if(10000 == counter) counter = 0; } sleep(5); } else { sleep(2); //Sleep for 2 secs & then check if the flag is set or not } } } ///******Callback when Client does a GET on URL "/SSEEvents"******** void SSEEvents_cb(struct evhttp_request *aReq, void *key) { if (EVHTTP_REQ_GET == aReq->type) { const char * getUri = evhttp_request_get_uri(aReq); if( NULL == getUri ) { evhttp_send_reply(aReq, 400, "Bad request", NULL); //Response back to client } req = (evhttp_request*) aReq; evhttp_request_own(aReq); evhttp_connection_set_closecb(evhttp_request_get_connection(aReq),&connectionClosed, KEY_STRING); evhttp_add_header(aReq->output_headers,"Content-Type","text/event-stream"); //Mandatory evhttp_send_reply_start(aReq, 200, "OK"); ///Start the reply & then set the flag so that chunk reply can be sent every 5 secs // Set this flag to true so that the sender thread can start sending chunk data startSend = true; } else { evhttp_send_reply(aReq, 501, " SET Not Implemented", NULL); } } int StartServer(char *aIPAddress, char *aPort) { base = event_base_new(); if (!base) { printf("Couldn't create an event_base: So Exiting"); return 1; } /* Create a new evhttp object to handle requests. */ http = evhttp_new(base); if (!http) { printf("Couldn't create evhttp: So Exiting...."); return 1; } //Register for callback for any HTTP request for url "SSEEvents" evhttp_set_cb(http, "/SSEEvents", SSEEvents_cb, this); /* Now we tell the evhttp what port to listen on */ uint16_t port = atoi(aPort); handle = evhttp_bind_socket_with_handle(http, aIPAddress, port); if (!handle) { printf("couldn't bind to IP & port %d. Exiting.",(uint16_t)port); return -1; } ///** Launch Thread to send chunk reply after http client makes request pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, (128 * 1024)); //128kbs int threadCreate = -1; threadCreate = pthread_create(&SenderThread, NULL, &sendChunk, NULL); event_base_dispatch(base); return 0; } int main(int argc , char *argv[]) { StartServer(argv[1], argv[2]); } Regards, Alap