Hi all again, Finally I got it working.
The problem is that apr_socket_accept blocks waiting for new connections, no matter what APR_SO_NONBLOCK nor apr_socket_timeout_set are. The pattern used at pollset-sample.c (http://dev.ariel-networks.com/apr/apr-tutorial/sample/pollset-sample.c) is as follows: use polling to "listen" for incoming connections. If there're any new connections available then proceed with accept, otherwise check the stop flag and continue. My code looks like this now: apr_socket_opt_set(server_socket, APR_SO_NONBLOCK, 0); apr_socket_timeout_set(server_socket, -1); apr_pollset_create apr_pollset_add (the server socket) while( !server->stop) { /* Check for availability of incoming connections or timeout */ status = apr_pollset_poll(pollset, apr_time_from_msec(500), ...); if (status == APR_TIMEUP) { /* On timeout check the stop flag and continue the loop */ continue; } // There should be an incoming connection now... apr_socket_accept ... process incoming connection } ... apr_pollset_destroy and other cleanup The signal handling routine just sets the server->stop flag now. Thanks all for your help and sorry if I've spammed the list a little bit: I think this clarifies others' doubts in the future. Cheers, Antonio 2011/7/6 Antonio Vieiro <[email protected]>: > Hi all again, > > I've noticed high CPU usage, and the fact is that there's a problem > with accept and socket timeouts and my code. > > I'll review > http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html#ss13.4 > and will post a correct code later on, just for the records. > > Cheers, > Antonio > > 2011/7/6 Antonio Vieiro <[email protected]>: >> Thanks guys, that's the approach I am following. The accept loop looks >> something like: >> >> apr_socket_opt_set(server_socket, APR_SO_NONBLOCK, 1); >> apr_socket_timeout_set(server_socket, 100); >> ... >> >> while (!server_stop) { >> do { >> status = apr_socket_accept(&client_socket, server_socket, server_pool); >> } while (!server_stop && APR_STATUS_IS_EAGAIN(status)); >> } >> >> And the signal handler just sets the "server_stop" flag to some non-zero >> value. >> >> This works fine on a Windows box, I'll try to see how well it behaves >> on a Unix box later on, and will post here just for the record. >> >> Thanks, >> Antonio >> >> 2011/7/5 Jeff Trawick <[email protected]>: >>> On Tue, Jul 5, 2011 at 11:00 AM, Wes Garland <[email protected]> wrote: >>>>> On both cases I imagine the server cleanup (apr_pool_destroy) should >>>>> be performed after the server loop, and not in the signal handler, >>>>> right? >>>> >>>> Correct. Your signal handler should just set a flag and return. The list >>>> of >>>> functions which can be safely run from a signal handler is very short, and >>>> malloc/free are not among them. >>>> >>>>> b) Shall I set a "keep-running" flag (using mutexes, i.e, a >>>>> synchronized flag) for shutdown on the SIGINT handler? >>>> >>>> Not mutexes. There is no need and the pthread mutex functions (which APR >>>> is >>>> implemented on top of on UNIX) are not async-signal safe. Here is my basic >>>> pattern: >>>> >>>> int die = 0; >>>> int signalHandler(signal) >>>> { >>>> die = signal; >>>> } >>>> >>>> while (!die) >>>> { >>>> /* accept, fork */ >>>> } >>> >>> Another piece of the puzzle is that APR on Unix can return EINTR >>> (signal interruption) from a few critical functions >>> (apr_socket_accept() and apr_poll*() and maybe something else), but >>> generally eats EINTR internally. This has an impact on when your main >>> thread gets to check the die flag. >>> >>> This is all rather non-portable. (You can get WSAEINTR from >>> apr_socket_accept() on Windows but that means something totally >>> different.) >>> >> >
