Return-Path: X-Original-To: apmail-apr-dev-archive@www.apache.org Delivered-To: apmail-apr-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 82CCF62DD for ; Wed, 6 Jul 2011 09:04:40 +0000 (UTC) Received: (qmail 18274 invoked by uid 500); 6 Jul 2011 09:04:39 -0000 Delivered-To: apmail-apr-dev-archive@apr.apache.org Received: (qmail 17893 invoked by uid 500); 6 Jul 2011 09:04:30 -0000 Mailing-List: contact dev-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Id: Delivered-To: mailing list dev@apr.apache.org Received: (qmail 17645 invoked by uid 99); 6 Jul 2011 09:04:24 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 06 Jul 2011 09:04:24 +0000 X-ASF-Spam-Status: No, hits=-0.0 required=5.0 tests=RCVD_IN_DNSWL_LOW,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (athena.apache.org: local policy) Received: from [209.85.210.50] (HELO mail-pz0-f50.google.com) (209.85.210.50) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 06 Jul 2011 09:04:19 +0000 Received: by pzk2 with SMTP id 2so5216020pzk.37 for ; Wed, 06 Jul 2011 02:03:58 -0700 (PDT) MIME-Version: 1.0 Received: by 10.142.234.3 with SMTP id g3mr3682809wfh.423.1309943038205; Wed, 06 Jul 2011 02:03:58 -0700 (PDT) Received: by 10.142.139.6 with HTTP; Wed, 6 Jul 2011 02:03:58 -0700 (PDT) X-Originating-IP: [213.164.164.164] In-Reply-To: References: Date: Wed, 6 Jul 2011 11:03:58 +0200 Message-ID: Subject: Re: Graceful server shutdown? From: Antonio Vieiro To: dev@apr.apache.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable 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 =3D apr_pollset_poll(pollset, apr_time_from_msec(500), ...); if (status =3D=3D 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 : > 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-tutor= ial-13.html#ss13.4 > and will post a correct code later on, just for the records. > > Cheers, > Antonio > > 2011/7/6 Antonio Vieiro : >> 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) { >> =A0do { >> =A0 =A0status =3D apr_socket_accept(&client_socket, server_socket, serve= r_pool); >> =A0} 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 : >>> On Tue, Jul 5, 2011 at 11:00 AM, Wes Garland 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.=A0 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.=A0 There is no need and the pthread mutex functions (whic= h APR is >>>> implemented on top of on UNIX) are not async-signal safe.=A0 Here is m= y basic >>>> pattern: >>>> >>>> int die =3D 0; >>>> int signalHandler(signal) >>>> { >>>> =A0 die =3D signal; >>>> } >>>> >>>> while (!die) >>>> { >>>> =A0 /* 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. =A0(You can get WSAEINTR from >>> apr_socket_accept() on Windows but that means something totally >>> different.) >>> >> >