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
> 

Reply via email to