Hi all,

I tried to use pthread to work with libevent. But the server can't send out data after recving a message. The detail is:

I can see that the data has been put into the evbuffer (output) using /evbuffer_add_cb(bufferevent_get_output(bev_), BufferCb, tp): BufferCb info->orig_size: 0 info->n_deleted: 0 info->n_added: 19

/But the underlying level didn't send out the data. and when another client coming, the server has no response (listener callback doesn't work). But when I close the server (kill the process), client can recv close signal.

I apt-get install libevent, and the version is : libevent-core-2.0-5_2.0.21-stable-1ubuntu1.14.04.1_amd64

What's the problem? Thanks!!!

    [server init]:

bev_ = bufferevent_socket_new(base_, fd, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_THREADSAFE);
    // set read callback and event callback
    bufferevent_setcb(bev_, ReadCb, NULL, EventCb, this);
    bufferevent_enable(bev_, EV_READ | EV_WRITE);

   [server read callback]:

bev_ = bufferevent_socket_new(base_, fd, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_THREADSAFE);
    // set read callback and event callback
    bufferevent_setcb(bev_, ReadCb, NULL, EventCb, this);
    bufferevent_enable(bev_, EV_READ | EV_WRITE);

// read is ok
    bufferevent_lock(bev_);
    struct evbuffer *input = bufferevent_get_input(bev_);
    return evbuffer_remove(input, buffer, len);
    bufferevent_unlock(bev_);

    // process read data..........

// write has problem
    bufferevent_lock(bev_);
    struct evbuffer *output = bufferevent_get_output(bev_);
    int re = evbuffer_add(output, buffer, len);
    bufferevent_unlock(bev_);


 [server event_base set]:

void Listener::Run(void* arg) {

    struct sockaddr_in sin;

    /* Clear the sockaddr before using it, in case there are extra
     *          * platform-specific fields that can mess us up. */
    memset(&sin, 0, sizeof(sin));
    /* This is an INET address */
    sin.sin_family = AF_INET;
    /* Listen on 0.0.0.0 */
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    /* Listen on the given port. */
    sin.sin_port = htons(port_);

    // TODO: LEV_OPT_THREADSAFE is necessary here?
    listener_ = evconnlistener_new_bind(listen_base_, AcceptConnCb, arg,
        LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_THREADSAFE, -1,
        (struct sockaddr*)&sin, sizeof(sin));

    if (!listener_) {
      LOG_ERROR("Couldn't create listener");
      return;
    }

    evconnlistener_set_error_cb(listener_, AcceptErrorCb);
    event_base_dispatch(listen_base_);
    return;
}



On 03/17/2016 08:50 PM, Azat Khuzhin wrote:
On Thu, Mar 17, 2016 at 05:14:22PM +0000, Tomer Heber wrote:
Hi Azat,

Correct me if I'm wrong.
Hi Tomer,

Indeed,

But he is using std c++11 "libraries" which are cross platform.
but if don't talking about cross platform then pthreads are ok on *nix,
and for win32 we have evthread_use_windows_threads()

But if you need cross platform, then you can just write something like
this (untested):
     #include <mutex>

     /** XXX: implement handle recursive locking! */
     static void *cxx_lock_alloc(unsigned /*locktype*/)
     {
         return reinterpret_cast<void *>(new std::mutex);
     }
     static void cxx_lock_free(void *lock_, unsigned /*locktype*/)
     {
         std::mutex *m = reinterpret_cast<std::mutex *>(lock_);
         delete m;
     }
     static int cxx_lock_lock(unsigned /*mode*/, void *lock_)
     {
         std::mutex *m = reinterpret_cast<std::mutex *>(lock_);
         m->lock();
     }
     static int cxx_lock_unlock(unsigned /*mode*/, void *lock_)
     {
         std::mutex *m = reinterpret_cast<std::mutex *>(lock_);
         m->unlock();
     }
     static int use_lock_unlock_profiler(void)
     {
         struct evthread_lock_callbacks cbs = {
             EVTHREAD_LOCK_API_VERSION,
             EVTHREAD_LOCKTYPE_RECURSIVE,
             cxx_lock_alloc,
             cxx_lock_free,
             cxx_lock_lock,
             cxx_lock_unlock,
         };
         evthread_set_lock_callbacks(&cbs);
         // evthread_enable_lock_debugging();

Also you can take a look at
https://github.com/libevent/libevent/blob/master/test/regress_bufferevent.c#L300

On the other hand, pthread is not cross platform.

So I think Michael shouldn't use pthreads and instead implement the callbacks 
(which is actually pretty straightforward).
***********************************************************************
To unsubscribe, send an e-mail to [email protected] with
unsubscribe libevent-users    in the body.

Reply via email to