Hi, Thank you I would try with the configuring libevent for multithreading. Mark also has the same suggestion.
Regarding, syncronize & connection close event. In actual code it is implemented properly. My bad I did not do that in the sample code. Regards, Alap ________________________________ From: Nir Soffer <nir...@gmail.com> To: libevent-us...@freehaven.net Sent: Thursday, May 31, 2012 10:11 AM Subject: Re: [Libevent-users] Crash in evhttp_send_reply_chunk() The example code you sent is expected to crash and burn randomly: - You use multiple threads, but you do not configure libevent to use multithreading - You do not synchronize the threads in your own code. For example, accessing startSend and req from multiple threads. - You do not handle the connection close event - it should stop the sendChunk thread. I suggest to use the event loop - Instead of the sendChunk thread, keep a 5 seconds timeout event for each connected client. Each time the timer runs, send a chunk if available. On Wed, May 23, 2012 at 5:24 PM, Alap Kumar Sinha <ala...@yahoo.com> wrote: 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 >