Lance Lovette | 1 Oct 2008 22:33
Picon
Favicon

Issue with evsignal_base in event_base_loop

I'm running my application (using libevent 1.4.8) through the Valgrind tool
Helgrind to help make sure I have no race conditions. It brought my
attention to the following line of code in event_base_loop (line 475 in the
current release, line 698 in trunk), that after inspection is confusing to
me.

if (&base->sig.ev_signal_added)
    evsignal_base = base;

If I'm reading this correctly, the statement "&base->sig.ev_signal_added"
evaluates to an address, so the condition is always true. Am I missing
something? Is this the desired behavior of this statement?

(As background, the issue that Helgrind reports is triggered by the fact
that I have two threads, each with their own event loop run by
event_base_loop. Since evsignal_base is shared between the two threads (it's
global) they both set it to their thread-local base, and Helgrind
accordingly reports the possibility of a race condition.)

Thanks!
Lance
Pengfei Di | 5 Oct 2008 14:45
Picon
Favicon

Does libevent support non-blocking RPC request?

Hello libevent group,

I want to build an asynchronous RPC client with libevent, but I am 
wondering whether it is possible at all. The evrpc.h file reference is 
not that easy for me to understand. Does anyone know some tutorial for 
the libevent, or some small sample code of evrpc.h.
(The RPC server that I use is already done and its interface (.x file) 
is also given. Now I have no idea, how to use the function of 
EVRPC_MAKE_REQUEST

<http://monkey.org/%7Eprovos/libevent/doxygen-1.4.3/evrpc_8h.html#ff0efcd7cb8b966256b5127960bd2c81>. 
)

Thanks a lot in advance.

Best Regards
Pengfei
Christopher Layne | 9 Oct 2008 21:48

Re: Implementing a deadline timer

On Tue, Sep 09, 2008 at 04:48:40PM -0500, Andrew Troschinetz wrote:
> Hi all,
>
> I'm just getting started with libevent and I was wondering how I might 
> implement a simple deadline timer with it.
>
> I'd like to be able to use do something like:
>
> 	void do_something(...) ...
> 	deadline_timer_wait(5, do_something); /* _non-blocking_, call 
> do_something() in 5 seconds */
> 	... perhaps less than 5 seconds later ...
> 	deadline_timer_nevermind(); /* whatever we're waiting on, stop waiting, 
> don't call do_something() */
>
>
> However I'm a bit confused as to how event_dispatch() is supposed to work. 
> Do I need to fork and then have the child call event_dispatch() in a loop:

Definitely not.

In this simple case, perform the initial timeout_set() and timeout_add().
Then call event_dispatch().

When the callback is called, do_something() in this case, do what you
need to do, then re-add the timeout event if you want it to fire again.

In the nevermind case, use timeout_del() to remove the timer. The
callback for it will then never be called.

(Continue reading)

Brian O'Kelley | 19 Oct 2008 18:32
Favicon

infinite accept loop when out of file descriptors

When a bound evhttp socket triggers for an accept with no free file descriptors, it fails with EMFILE or ENFILE, the event isn’t cleared and thus continues to call the accept handler until the connection is dropped. This seems like a denial of service vulnerability.

I’ve been thinking about how to handle this elegantly, and I’m wondering if it makes sense for the calling program to allocate libevent a certain number of file descriptors. Then, libevent can do something smart (allow incoming connections to pile up until we have a free fd? disallow keep-alives if we’re low on fds?).

Thoughts?

Brian
_______________________________________________
Libevent-users mailing list
Libevent-users <at> monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users
Brian O'Kelley | 19 Oct 2008 21:30
Favicon

Does evhttp_make_request always call the callback?

I’m seeing interesting behavior. When evhttp_make_request fails (which I can make happen by restricting the number of fds available), it seems that sometimes the callback on the connection is called, and sometimes it’s not. Is there a best practice for what to do when this fails? I don’t care if the callback is called, but I need to put cleanup logic either in there or in my failure handler (right now it gets called twice – sometimes – which causes crashes).

Thanks!
Brian
_______________________________________________
Libevent-users mailing list
Libevent-users <at> monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users
jad chamcham | 20 Oct 2008 09:36
Picon
Favicon

event_queue_remove: event not on queue?

.hmmessage P { margin:0px; padding:0px } body.hmmessage { FONT-SIZE: 10pt; FONT-FAMILY:Tahoma } .hmmessage P { margin:0px; padding:0px } body.hmmessage { FONT-SIZE: 10pt; FONT-FAMILY:Tahoma } Hi,
I'm new to libevent. I'm having some issues with my server program on multi-processor machines. The same code seemed to work fine on a uniprocessor machine. The machine is running FC8, kernel 2.6.23.1-42.

The errors I'm getting are:
[err] event_queue_remove: 0x9bcb0c4(fd 293) not on queue 8

and sometimes
event_process_active: Assertion `activeq != ((void *)0)' failed

The server consists of a main dispatch thread running evhttp and multiple worker threads, each with their own instance of libevent.
The main dispatch thread gets an http request, sticks it onto a worker thread's queue, and then writes a byte to the pipe of the worker thread to notify it.
The worker thread will respond to the http request.

Here's the skeleton of my program

main() {
   httpd = evhttp_start("0.0.0.0", 8080);
   evhttp_set_gencb(httpd, generic_handler, NULL);
   event_dispatch();
   evhttp_free(httpd);
}

generic_handler(evhttp_request *req, void *arg)
{
    pick worker thread 'w'
    stick request on worker thread queue
    write(thread[w].send_fd, "", 1);
}

Each thread's initialization includes:
thread->base = event_init();
event_set(thread->event, thread->receive_fd, EV_READ | EV_PERSIST, libevent_process, thread);
event_base_set(thread->base, thread->event);
event_add(thread->event, 0);

libevent_process(int fd, short which, void *arg)
{
    if (read(fd, buf, 1) != 1) error;
   
    if item on queue, respond then free item
}

Could you let me know which assumptions I'm violating here?
Thanks,
- Jad
_______________________________________________
Libevent-users mailing list
Libevent-users <at> monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users
Adam Grossman | 20 Oct 2008 23:00
Favicon

restarting main loop immediately, i think....

i tried looking in the mailing list to see if this has already been 
answered, but i could not find it.

my prog is sitting in the main loop, and i am using "poll". an event 
comes in, a thread is spawned off.  meanwhile, the main thread goes back 
to the main loop.  The spawned thread needs to add a new event (e.g. 
calling event_add with EV_READ on a socket) and then the thread exits.  
the problem is the event is added after the main thread goes back to the 
main loop, and the new event is not added to poll (i checked via 
strace), until another event is called and the main loop is started again.

what i did for a hack is added an alarm for 1 second, but i do not like 
relying on it, and since the spawned thread is not persistant, i do 
think adding another event base is the way to go.  any ideas on how to 
get this working?  i am thinking the only way is to restart the main 
loop immediately, but i could not find a way to do that cleanly.

thank you very much,
-=- adam grossman
Kaiwang Chen | 21 Oct 2008 08:51
Picon

(no subject)


_______________________________________________
Libevent-users mailing list
Libevent-users <at> monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users
Victor Chang | 29 Oct 2008 11:27

event_base's tv_cache not reset after event_base_loop()

Hi libevent-users,

I noticed something odd and wanted to see if this is a bug or
if I'm doing something wrong:

event_base's tv_cache is not getting cleared after event_base_loop()
exits. Calling event_add() again much later can cause an expired
timestamp to be registered.

Background:

I'm working on a program that uses libevent in this manner:

1) Start program and call event_init().
2) Call event_set(), event_add() to monitor some connections.
3) Call event_dispatch() to start the event loop.
4) During event loop, callbacks are triggered which will eventually
   call event_del() on each connection when all the work is done.
5) event_dispatch() automatically returns when there are no more
   connections to process.
6) Program continues, time passes, unrelated stuff happens, and
   eventually we go back to step 2 again.

Problem:

event_base's tv_cache is cleared and set inside event_base_loop().
But tv_cache is not cleared when event_base_loop() returns.

When we return to Step #2, we call event_add(). This calls gettime()
which will use the tv_cache timestamp since it's non-zero now.  This
cached timestamp might be pretty old.  event_add() calls
evutil_timeradd() to compute the expiration timestamp, but
the resulting expiration timestamp could already be in the past. When
event_dispatch() gets called, it immediately thinks that the event has
already timed out due to the old timestamp.

Am I using libevent properly?:

I'm relatively new to using libevent, so I wondered if I was doing
something wrong :-)

I suppose most typical libevent applications just sit in
event_base_loop() forever until termination. In this typical case, the
tv_cache is getting refreshed frequently enough so that it's not too
old. (Assuming callbacks don't take excessively long)

Intuitively, I would think that event_set/add() could get called
before and during event_dispatch(). And when no more events need
to be monitored, event_dispatch() returns and the event_base should
be back in its "initial" state, ready to be reused if needed.

Right now, it seems I'd have to call event_init() again to
create a new event_base with a blank tv_cache. (Not to mention
calling event_base_free() to dispose of the original event_base.)
This seems like overkill...

Your thoughts?
Victor
Dan Kegel | 29 Oct 2008 13:05

Re: event_base's tv_cache not reset after event_base_loop()

On Wed, Oct 29, 2008 at 3:27 AM, Victor Chang <vchang <at> rawbw.com> wrote:
> I suppose most typical libevent applications just sit in
> event_base_loop() forever until termination.

FWIW, when I ported Chromium's networking to libevent,
I used EVLOOP_ONCE, so event_base_loop() never
lingers; see
http://src.chromium.org/svn/trunk/src/base/message_pump_libevent.cc
But I don't use libevent's timeouts at all.

(OT: I'm terribly tempted to switch to using edge-triggered
mode (in libevent trunk); that way my app would
never have to do event_set, event_add, or event_del
ever again... I'm a big boy, I can manage my own
state, and it would reduce the number of syscalls.
But I probably won't bother, since the extra syscalls
aren't bothering me right now, and I seem to
have gotten those pesky event masks right.)
- Dan

Gmane