Re: timer behaviour
On 06/13/2011 11:23 PM, Juan Pablo L wrote: attached is source for database pool module, Besides from the locking issues outlined here, you are doing it wrong. You can run a postgres database connection completely nonblocking, without threads. While it is not easy to get things right the first time - better read the docs twice, it is much easier to use the nonblocking interface than dealing with threads mutexes. If the database-con is busy, queue the request, if the database-con is available run a request from the queue, if the database-con wants to read, EV_READ, if the database-con wants to write, EV_WRITE to the appropriate callback. Give each request a callback to report the result, call the callback once the query is done and block issuing new requests on the database-con during while the callback is running. As there is very little computation required on the client side of a database connection you do not need threads anyway, and not having mutexes is likely to make the code easier and more scalable therefore. ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: ev_is_active - at which point?
Marc Lehmann wrote: On Wed, May 26, 2010 at 12:01:28AM +0200, com...@gmx.ch com...@gmx.ch wrote: But, ev_is_active reports the timer is not active, I do not disable the timer, and the timers callback gets fired afterwards. That's as documented (see ev_TYPE_start/stop, ev_is_active and ev_is_pending). Thats the problem. Maybe, but you need to explain why that is a problem? Not reading the docs properly was the problem. Markus ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
ev_is_active - at which point?
Hi, I got the following problem with ev_is_active(): I got a ev_timer, and it gets started, then something which takes a lot of time happens, and I'd stop the timer if ev_is_active claims the timer is still active. But, ev_is_active reports the timer is not active, I do not disable the timer, and the timers callback gets fired afterwards. Thats the problem. ev_is_active reports the timer is inactive, and the callback gets fired. Sounds scary, yes. I used gdb to verify: ev_is_active is false: (gdb) p con-events.dns_timeout $6 = {active = 0, pending = 1, priority = 0, data = 0x9a2b8c8, cb = 0x805a410 the_cb, at = -3.4154873266816139, repeat = 0} but later on, the callback fires: (gdb) p con-events.dns_timeout $7 = {active = 0, pending = 0, priority = 0, data = 0x9a2b8c8, cb = 0x805a410 the_cb, at = -3.4154873266816139, repeat = 0} I noticed the 'pending' field, so when is a not repeating ev_timer inactive? If I ask to disable an ev_timer in the same ev_loop iteration which would fire the callback (ev_timer.pending = 1), is the ev_is_active(ev_timer) meant to be true or false? I'd expect it to be true - as I did not call ev_timer_stop on it yet, and the callback did not come in yet, but I think I'm wrong. Attached is a sample program, t1_cb is expected to stop t2, so t2_cb never gets called, but t2_cb is called always. ./timertest called t1_cb loop 0x7fd720899200 w 0x601100 revents 256 called t2_cb loop 0x7fd720899200 w 0x601080 revents 256 Thanks, Markus /* gcc -Wall -o timertest timertest.c -lev */ #include stdio.h #include unistd.h #include ev.h #include time.h struct ev_timer t1; struct ev_timer t2; struct ev_signal s1; void waste(time_t s) { time_t now = time(NULL); int i = 0; while((now + s) time(NULL)) i++; } void t1_cb(struct ev_loop *loop, struct ev_timer *w, int revents) { printf(called %s loop %p w %p revents %i\n, __PRETTY_FUNCTION__, loop, w, revents); if( ev_is_active(t2) ) { printf(stopping t2\n); ev_timer_stop(loop, t2); } } void t2_cb(struct ev_loop *loop, struct ev_timer *w, int revents) { printf(called %s loop %p w %p revents %i\n, __PRETTY_FUNCTION__, loop, w, revents); } int main() { struct ev_loop *loop = ev_default_loop (0); ev_timer_init(t1, t1_cb, 1.0, 0); ev_timer_init(t2, t2_cb, 5.0, 0); ev_timer_start(loop, t1); ev_timer_start(loop, t2); waste(6); ev_loop (loop, 0); return 0; } ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: [ANN] x0 HTTP server and framework (initial release)
Marc Lehmann wrote: On Thu, Apr 01, 2010 at 10:53:39AM +0200, Graham Leggett minf...@sharp.fm wrote: You might be tempted to keep two socket watchers going for listening to socket read events, and socket write events, but to support SSL This is the mess how it is commonly implemented, and it is indeed horrors. I've had the non-blocking ssl challenge too, and I use two socket watchers, I know it can be done using a single watcher, but ... I'd call it a tradeoff, using two io watchers simplified the code and therefore I decided to take the performance impact into account. In fact, given the possibility, I use two io watchers for every type of connection, even tcp and udp, and a multitude of timers for each connection type to provide timeouts for all kinds of things I want to be able to deal with (idle, sustain, listen, throtte_(in,out), connecting, dnsresolve, close, handshake, reconnect). This makes a total of * 2 io watchers * 10 timers - 12 watchers per connection where 1 io watcher (in) and 2 timers (idlesustain) are active most of the time. I'm totally aware could be done with 2 watchers, one for io, and one timeout and some internal list to have only the 'next' timeout active in libev, but I don't feel bad about it. In fact, libev performs that great, I did not even notice a when it had about 6000 connections. So, if you don't need the extra tidbit of performance, you can keep things simple. A much easier way is to decouple openssl from the socket altogether, i.e. don't let it do socket I/O, instead let it do I/O from/two two BIO buffers, which simplifies things a lot - no need to watch for SSL_WANT_READ and other issues, no need to switch watcher state based on return codes etc. As you have to call SSL_write again with the same arguments again if you get a SSL_WANT_* error, you need two write queues, so you can provide the same arguments. I was looking for rate limiting, and therefore I calculate how much I'm allowed to read/write. To prevent reading/writing too small chunks, I allow reading/writing some bytes more - the amount is calculated relative to the allowed speed and already sent data for the sliding window-, and suspend the read/write io watchers in case I read/write to much, and use timers to wake up again. As there are many ways to use non-blocking openssl in a wrong way, I'm glad it works. Proper openssl shutdown was a real problem to me, as it did not work at all, turned out the problem was within openssl, and got patched in 0.9.8m. I was looking at using BIOs myself, but I was not sure about rate limiting when using bios, and there is 'little' examples/documentation, besides some ascii image to illustrate how to design openssl nonblocking with bios. I wanted to make a C example for quite some time, but didn't get to it yet. I saw libevent2 providing (rate limited) non-blocking openssl, but I'd say there is some (more) feature creep in libevent2, which makes it (even) less attractive to me. Not even talking about performance - I got no numbers on libevent2, I prefer a simple api over features (I do not need in most cases). But example code for (maybe even rate limited?) nonblocking ssl with bios on top of libev would be great. ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: problem with poll_poll() under FreeBSD
Zajcev Evgeny wrote: as it was predicted, FreeBSD's poll() returned incorrect value :(. I've skimed poll() implementation in FreeBSD and did not found any place that can give such results, it might be due to lack of knowledge. I'll try to contact freebsd community.. The bug is obviously known - at least it was reported already: http://forums.freebsd.org/showthread.php?t=10270 ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: Optimal multithread model
I have something similar, therefore how I did it. All polling is done by libev in the main-loop, a single main loop. If a connection is established and processing the data needs some time, I remove the watchers from the loop, and creates a task from the data to process and the function to process the data, and pushes this set to an glib thread pool. The thread is allowed calls the function to process the data with the data as argument, once it is done, it creates its result set, the data and a function which will deal with the result-data, and pushes this set to an async queue. To signal libev there is something in the async queue, I use ev_async from the thread. libev catches the ev_async, I remove all pending sets from the async queue, call the provided function with the data provided. The function provided can rearm the watchers for the loop, and continue in the main loop. It's rather simple, but works as expected. Markus ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: [PATCH 2] fix broken strict aliasing
Hi, Marc Lehmann wrote: If you are unclear on what aliasing itself means, I can write a short paragraph to explain... (the iso c documents ae not that hard to read, though, imho, with the exception of structure member aliasing). I've had the same discussion before, but just pulled my claim as Marc was involved in gcc development, and I did not feel I could make a point. I've had the same problems, -Wall -Werror, as I consider the compiler my friend and if he wants to tell me something it usually pays of when I'm listening to him. But, I totally understand if Marc says it is not a libev bug, and rejects to add casts to proper code - to fix compiler misbehavior. Therefore I'd be glad to get more information on the topic. Thanks for the offer. Markus ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: libev 3.8 threads signals
Marc Lehmann wrote: On Thu, Sep 24, 2009 at 03:31:30PM +0200, com...@gmx.ch com...@gmx.ch wrote: I have a g_thread_pool and libev, following pseudocode I don't know what g_thread_pool does, but if it messes with the signal mask, then it should just not do that, at elast not for signals you register with libev. libev (just like any other event loop) requires you to not touch resources it manages, which includes SIGCHLD and any signal handler you install via it. If something else in your program messes with those signals in any way, then either that part is broken, or the part that installs the signal watcher in libev. These resources are simply nto sharable, as much as we'd like them to be. Only one can manage it, which is why libev allows you to multiplex all those signals. You are right, g_thread_pool messes up the signals. rt_sigprocmask(SIG_BLOCK, [INT CHLD], NULL, 8) = 0 syscall_289(0x5, 0x7fbf0d0606b0, 0x8, 0, 0x98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0x5 rt_sigprocmask(SIG_BLOCK, [HUP INT CHLD], NULL, 8) = 0 syscall_289(0x5, 0x7fbf0d0606b0, 0x8, 0, 0x5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0x5 Thanks for reply. Markus ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: libev 3.8 threads signals
You are right, g_thread_pool messes up the signals. rt_sigprocmask(SIG_BLOCK, [INT CHLD], NULL, 8) = 0 syscall_289(0x5, 0x7fbf0d0606b0, 0x8, 0, 0x98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0x5 rt_sigprocmask(SIG_BLOCK, [HUP INT CHLD], NULL, 8) = 0 syscall_289(0x5, 0x7fbf0d0606b0, 0x8, 0, 0x5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0x5 Hrm, further invesigation shows that was libev signal handler code ... The glib thing does not touch signal handler the signal handler directly: mmap(NULL, 8392704, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f04a18e7000 mprotect(0x7f04a18e7000, 4096, PROT_NONE) = 0 clone(child_stack=0x7f04a20e7250, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f04a20e79e0, tls=0x7f04a20e7950, child_tidptr=0x7f04a20e79e0) = 27442 futex(0x24d5b90, FUTEX_WAKE_PRIVATE, 1) = 1 maybe the CLONE_SIGHAND got something to do with it? As mentioned before, this worked fine with libev 3.6. Markus ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: libev 3.8 threads signals
Marc Lehmann wrote: On Thu, Sep 24, 2009 at 04:46:42PM +0200, com...@gmx.ch com...@gmx.ch wrote: Besides, why does the list reply to user per default? Excuse the incorrect question, should have been is the reply-to header missing by design for the list? Markus ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: libev 3.8 threads signals
Luca Barbato wrote: How is broken exactly? I'm tracking some yet another strange issues in feng that cropped up recently and I'm using thread pools and libev signal handlers as well, so even if I'm pretty sure that isn't the same issue I'd like to know what is going to bite me sooner or later =) Ouch, forgot to mention, the signal handlers do not work any longer if I create threads before starting the signal handlers. Markus Besides, why does the list reply to user per default? ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev