2016-08-11 8:43 GMT+02:00 Luca Toscano <toscano.l...@gmail.com>:

>
>
> 2016-08-09 15:02 GMT+02:00 Luca Toscano <toscano.l...@gmail.com>:
>
>> Thanks a lot for the feedback, trying to answer to everybody:
>>
>> 2016-08-05 15:19 GMT+02:00 Jim Jagielski <j...@jagunet.com>:
>>
>>> If APR_POLLSET_WAKEABLE was more universal and, therefore,
>>> more widely tested, I'd be +1... as it is, let's see what
>>> the feedback is.
>>
>>
>> Definitely, we should find a good way to test this if we'll reach
>> consensus on a patch. Maybe some stress tests plus "incubation" in trunk
>> for a while could be good enough, but I agree that it would be an important
>> change to make with extreme care.
>>
>> 2016-08-05 15:26 GMT+02:00 Yann Ylavic <ylavic....@gmail.com>:
>>
>>> On Fri, Aug 5, 2016 at 3:19 PM, Yann Ylavic <ylavic....@gmail.com>
>>> wrote:
>>> > Hi Luca,
>>> >
>>> > On Fri, Aug 5, 2016 at 2:58 PM, Luca Toscano <toscano.l...@gmail.com>
>>> wrote:
>>> >>
>>> >> 2016-08-04 17:56 GMT+02:00 Luca Toscano <toscano.l...@gmail.com>:
>>> >>>
>>> >>> Would it be possible to avoid them adding APR_POLLSET_WAKEABLE to the
>>> >>> event_pollset flags and calling apr_pollset_wakeup right after
>>> >>> apr_skiplist_insert?
>>> >
>>> > That might be possible, but there is more than apr_skiplist_insert()
>>> > to handle I'm afraid, see below.
>>> >
>>> >>
>>> >>  Very high level idea: http://apaste.info/MKE
>>> >
>>> > The timeout_interval also handles the listener_may_exit (and
>>> > connection_count == 0 in graceful mode), your patch seems not handle
>>> > them...
>>>
>>
>> You are right, and IIUC these are the use cases to cover:
>>
>> 1) listener thread(s) blocked on apr_pollset_poll and a call to
>> wakeup_listener (that afaiu is the only one setting listener_may_exit to 1);
>> 2) listener thread(s) blocked on apr_pollset_poll, listener_may_exit = 1
>> and connection_count still greater than zero. The last connection cleanup
>> (that calls decrement_connection_count registered previously
>> with apr_pool_cleanup_register) should be able to wake up the listener
>> that in turns will be able to execute the break in the following block:
>>
>>         if (listener_may_exit) {
>>             close_listeners(process_slot, &closed);
>>             if (terminate_mode == ST_UNGRACEFUL
>>                 || apr_atomic_read32(&connection_count) == 0)
>>                 break;
>>         }
>>
>> I would also add another one, namely if the pollset create does not
>> support APR_POLLSET_WAKEABLE. This would mean that in absence of
>> apr_pollset_wakeup we should rely on apr_pollset_poll with the 100 ms
>> timeout, keeping it as "fallback" to ensure compatibility with most of the
>> systems.
>>
>>
>>> > The listener_may_exit case may be easily handled in wakeup_listener
>>> > (one more apr_pollset_wakeup() there), however the connection_count
>>> > looks more complicated.
>>> >
>>> > IOW, not sure something like the below would be enough...
>>> >
>>> > Index: server/mpm/event/event.c
>>> > ===================================================================
>>> > --- server/mpm/event/event.c    (revision 1755288)
>>> > +++ server/mpm/event/event.c    (working copy)
>>> > @@ -484,6 +484,7 @@ static void close_worker_sockets(void)
>>> >  static void wakeup_listener(void)
>>> >  {
>>> >      listener_may_exit = 1;
>>> > +    apr_pollset_wakeup(event_pollset);
>>> >      if (!listener_os_thread) {
>>> >          /* XXX there is an obscure path that this doesn't handle
>>> perfectly:
>>> >           *     right after listener thread is created but before
>>>
>>> Or rather, in wakeup_listener():
>>>
>>> @@ -493,6 +493,9 @@ static void wakeup_listener(void)
>>>          return;
>>>      }
>>>
>>> +    /* unblock the listener if it's waiting for a timer */
>>> +    apr_pollset_wakeup(event_pollset);
>>> +
>>>      /* unblock the listener if it's waiting for a worker */
>>>      ap_queue_info_term(worker_queue_info);
>>>
>>> _
>>>
>>> > @@ -696,7 +697,9 @@ static apr_status_t decrement_connection_count(voi
>>> >          default:
>>> >              break;
>>> >      }
>>> > -    apr_atomic_dec32(&connection_count);
>>> > +    if (!apr_atomic_dec32(&connection_count) && listener_may_exit) {
>>> > +        apr_pollset_wakeup(event_pollset);
>>> > +    }
>>> >      return APR_SUCCESS;
>>> >  }
>>>
>>
>>  I like these suggestions, they look good! (This assuming that what I
>> have written above is correct, otherwise I didn't get them :)
>>
>
> I applied Yann's suggestions and added some checks to allow wakeable and
> non wakeable listeners: http://apaste.info/mke
>
> This is a very high level prototype, please let me know if you have more
> suggestions (of course the discussion around testing and reliability of
> APR_POLLSET_WAKEABLE still holds).
>

This patch might also miss another point, namely the calls to
process_timeout_queue to manage Keep Alive timeouts, lingering closes and
write completion. IIUC mpm-event explicitly process them after each wake up
(every 100ms).

Will work more on it, in the meantime thanks to all for the feedback!

Luca

Reply via email to