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#L300On 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 majordomo@xxxxxxxxxxxxx with unsubscribe libevent-users in the body. |