> On Sat, Nov 03, 2007 at 03:45:39PM -0700, William Ahern <[EMAIL PROTECTED]> > wrote: > > Curious how you managed to do this. Are you checking the process PID on each > > loop? > > I considered that, but I think its too slow (one also needs to be careful > that watchers don't change e.g. epoll state until the getpid check is > done), or at leats I think I don't want that speed hit, no matter what.
After giving signal handling and threads a lot of thought, I came to these conclusions: - requiring pthreads or windows mutexes by default is not acceptable, but thats the only way to distribute signal events among event loops properly, or globally among many threads if signal handling were global. - the only way to do it without locking is to only allow a single loop to handle events. This is the interface I came up with to manage multiple loops (which I think makes more sense than the interface currently in libevent): struct ev_loop *ev_default_loop (int methods); void ev_default_destroy (void); void ev_default_fork (void); this would create "the default" loop (event_base). ev_default_loop would always create the same loop, and it would be the one to use for third-party libraries in general, too. The fork method can be called in the parent or child (or even in both, or without forking), and it would destroy and recreate the kernel state but keep all the watchers for the default loop. struct ev_loop *ev_loop_new (int methods); void ev_loop_destroy (EV_P); void ev_loop_fork (EV_P); This would create additional loops (event_bases). The difference is that these cannot handle signals (or child watchers) at all, with the default loop being the only one to do signal handling. This would be consistent with how signals are usually handled in a pthreads environment: block signals in all threads and in one thread handle them all (sigwait, or using the default mainloop). No locking inside libevent would be required this way. I'll implement this in my libev replacement code, unless somebody else comes up with a better idea. One such idea that isn't better, but different, would be to require the user to provide mutex support, such as in ev_init_locking (size, init_cb, lock_cb, unlock_cb, free_cb) or similar, then use locking and let any event loop handle the signals and distribute signal events to the relevant loops. But I am not sure how much locking would be required and I assume it would be a lot, as one would need to handle the case where one thread handles a signal for an event_base currently in use by another thread. Looking at the code in libevent, it seems that signals get handled by whatever loop was started last, so signal handling is not reliable at all unless one registers the signal handlers in all threads, which is hard to do in a thread-safe manner (for the user code). Having a deterministic model where one loop handles all that would definitely an improvement over this. -- The choice of a Deliantra, the free code+content MORPG -----==- _GNU_ http://www.deliantra.net ----==-- _ generation ---==---(_)__ __ ____ __ Marc Lehmann --==---/ / _ \/ // /\ \/ / [EMAIL PROTECTED] -=====/_/_//_/\_,_/ /_/\_\ _______________________________________________ Libevent-users mailing list Libevent-users@monkey.org http://monkey.org/mailman/listinfo/libevent-users