Re: [Libevent-users] Unable to use event_base_loopexit on another thread's event base

2009-08-17 Thread Nick Mathewson
On Thu, Jul 30, 2009 at 06:21:03PM +0200, Bas Verhoeven wrote:
 [...]
> 
> But, I gather from that note that it should be possible now?

Indeed it should be!  Did you set up threading on the event_base
before running it?  Is the base notifiable?

You might want to try poking through event.c in the Libevent source to
see how it's meant to work.  event_base_loopexit(base,tv) is an alias for
event_base_once(base, -1, EV_TIMEOUT, event_loopexit_cb, event_base,
tv).

The event_base_once function creates an event and adds it with
event_add which calls event_add_internal.  The synchronization is
meant to happen in event_add_internal, when it says:

  if (res != -1 && !EVBASE_IN_THREAD(base))
 evthread_notify_base(base);

Now, this _should_ wake up the event base, so long as Libevent has
been told about the threading system and it knows how to notify the
base to wake up for stuff.  Since your application uses pthreads, the
easiest way to do this is by making sure to call
evthread_use_pthreads() before you initialize the event_base.

(If you *did* set up locking and thread-ID callbacks before creating
the base, then we have a bug here that we need to solve.)

-- 
Nick

___
Libevent-users mailing list
[email protected]
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Unable to use event_base_loopexit on another thread's event base

2009-07-31 Thread Clint Webb
On Fri, Jul 31, 2009 at 8:44 PM, Bas Verhoeven  wrote:

> Bas Verhoeven wrote:
> > Hello again,
> >
> > I'm currently working with libevent 2.02-alpha and I encountered a weird
> > problem when I try to exit the base loop from another thread.
> >
> >
> I seem to have found a workaround for this problem now.
>
> Instead of using 'event_base_dispatch(base)' I am now using
> 'event_base_loop(base, EVLOOP_NONBLOCK)' in a while(!shutdown) loop.
> This seems to work fine: the thread shuts down instantly and libevent
> cleans up.
>
> I also tried experimenting with the 'EVLOOP_ONCE' flag but then I
> encountered the same problem as when using no flags at all: libevent
> never really quits the loop, and I don't really get why it does that.
>
> I seem to be able to continue with this workaround, but I doubt that
> it's the best way to handle this.  So, if anyone has any suggestions on
> how to handle this differently, then please let me know.
>
>
>
That sounds like a pretty good work around, but have you though about
designing your system so that you dont have to break out of the loop in
order to exit?

When I handle a SIGINT, I close my listeners (and removing their events),
and tell my existing connections to finish what they are doing.  They can
then continue until they all close.  When the last client closes (or timeout
reached, and forcibly closed) and the event removed, then the loop
automatically exits, and my app shuts down.

As long as I have the listener events in the system, the loop keeps running,
but without them, it will not add any new clients, and the existing clients
will eventually close or be forcibly closed after a timeout (yes, it helps
to setup a timeout on your read/write handlers).  That way, the client nodes
can close cleanly.



-- 
"Be excellent to each other"
___
Libevent-users mailing list
[email protected]
http://monkeymail.org/mailman/listinfo/libevent-users


Re: [Libevent-users] Unable to use event_base_loopexit on another thread's event base

2009-07-31 Thread Bas Verhoeven
Bas Verhoeven wrote:
> Hello again,
>
> I'm currently working with libevent 2.02-alpha and I encountered a weird 
> problem when I try to exit the base loop from another thread.
>
>   
I seem to have found a workaround for this problem now.

Instead of using 'event_base_dispatch(base)' I am now using 
'event_base_loop(base, EVLOOP_NONBLOCK)' in a while(!shutdown) loop. 
This seems to work fine: the thread shuts down instantly and libevent 
cleans up.

I also tried experimenting with the 'EVLOOP_ONCE' flag but then I 
encountered the same problem as when using no flags at all: libevent 
never really quits the loop, and I don't really get why it does that.

I seem to be able to continue with this workaround, but I doubt that 
it's the best way to handle this.  So, if anyone has any suggestions on 
how to handle this differently, then please let me know.


___
Libevent-users mailing list
[email protected]
http://monkeymail.org/mailman/listinfo/libevent-users


[Libevent-users] Unable to use event_base_loopexit on another thread's event base

2009-07-30 Thread Bas Verhoeven
Hello again,

I'm currently working with libevent 2.02-alpha and I encountered a weird 
problem when I try to exit the base loop from another thread.

When I developed my application and tested it as a single-thread 
application I had no problems shutting down the base loop with 
'event_base_loopexit(base, NULL);' when using the following setup:

void close_stuff(int dummy)
{
event_base_loopexit(base, NULL);
}

int main(void)
{
signal(SIGHUP, close_stuff);

base = event_base_new();
// ..snip.. socket creation
event_base_dispatch(base);

// ..snip.. cleanup
event_base_free(base);

return 0;
}

If I would then send a SIGHUP signal to the program, the loop would exit 
almost immediately and it would clean up all memory, etc.

I then copied the code to a module for one of my programs. This code 
looks like this:

void module_destroy()
{
if (base != NULL)
{
printf("Exiting event loop..\n");
event_base_loopexit(base, NULL);
}

printf("Unloading module\n");
}

void *module_loop(void* ptr)
{
(void)ptr;

base = event_base_new();
// ..snip.. socket creation
event_base_dispatch(base);

// ..snip.. cleanup
event_base_free(base);
return 0;
}

The only difference with the previous code is that the 'module_loop' 
code runs in a (pthread) thread. In both cases 'base' is global. The 
code itself works fine, just as in the single-thread application, so no 
problems there.

The problems arise however when then module gets notified that it needs 
to be unloaded. The 'module_destroy' function is then called in the main 
thread (e.g. not the same thread as the libevent code).

When I then call the 'event_base_loopexit(base, NULL);' nothing happens. 
The libevent loop keeps running and does not appear to end. All 
connections made also stay alive long after the module has been 
unloaded. The main thread then crashes after a few minutes, probably 
because libevent is still accessing things.

I already tried adding a 'sleep(3);' after the loopexit call to give the 
loop some time to close, but that doesn't help either - it just freezes 
the main thread.

Am I doing something wrong here? According to the "libevent book" this 
was not supported before 2.0:

"Because event_base did not support locking before Libevent 2.0, these 
functions weren’t completely threadsafe: it was not permissible to call 
the _loopbreak() or _loopexit() functions from a thread other than the 
one executing the event loop.".

But, I gather from that note that it should be possible now?


___
Libevent-users mailing list
[email protected]
http://monkeymail.org/mailman/listinfo/libevent-users