apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Antonio Vieiro <anto...@antonioshome.net>
Subject Re: Graceful server shutdown?
Date Wed, 06 Jul 2011 09:03:58 GMT
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 <antonio@antonioshome.net>:
> 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 <antonio@antonioshome.net>:
>> 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 <trawick@gmail.com>:
>>> On Tue, Jul 5, 2011 at 11:00 AM, Wes Garland <wes@page.ca> 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.)
>>>
>>
>

Mime
View raw message